Added the pic16 port for Martin Dubuc.
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
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 #ifdef HAVE_SYS_ISA_DEFS_H
41 #include <sys/isa_defs.h>
42 #else
43 #ifdef HAVE_MACHINE_ENDIAN_H
44 #include <machine/endian.h>
45 #else
46 #ifdef HAVE_ENDIAN_H
47 #include <endian.h>
48 #else
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #endif
53 #endif
54 #endif
55 #endif
56
57 #include "common.h"
58 #include "SDCCpeeph.h"
59 #include "ralloc.h"
60 #include "pcode.h"
61 #include "gen.h"
62
63
64 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
65 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
66 void pic16_genMult8X8_8 (operand *, operand *,operand *);
67 pCode *pic16_AssembleLine(char *line);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *popRegFromString(char *str, int size, int offset);
71 static void mov2w (asmop *aop, int offset);
72 static int aopIdx (asmop *aop, int offset);
73
74 static int labelOffset=0;
75 extern int pic16_debug_verbose;
76 static int optimized_for_speed = 0;
77
78 /* max_key keeps track of the largest label number used in 
79    a function. This is then used to adjust the label offset
80    for the next function.
81 */
82 static int max_key=0;
83 static int GpsuedoStkPtr=0;
84
85 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
86 unsigned int pic16aopLiteral (value *val, int offset);
87 const char *pic16_AopType(short type);
88 static iCode *ifxForOp ( operand *op, iCode *ic );
89
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
91
92 /* this is the down and dirty file with all kinds of 
93    kludgy & hacky stuff. This is what it is all about
94    CODE GENERATION for a specific MCU . some of the
95    routines may be reusable, will have to see */
96
97 static char *zero = "#0x00";
98 static char *one  = "#0x01";
99 static char *spname = "sp";
100
101 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
102 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
103 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
104 static char **fReturn = fReturnpic16;
105
106 static char *accUse[] = {"a","b"};
107
108 //static short rbank = -1;
109
110 static struct {
111     short r0Pushed;
112     short r1Pushed;
113     short accInUse;
114     short inLine;
115     short debugLine;
116     short nRegsSaved;
117     set *sendSet;
118 } _G;
119
120 /* Resolved ifx structure. This structure stores information
121    about an iCode ifx that makes it easier to generate code.
122 */
123 typedef struct resolvedIfx {
124   symbol *lbl;     /* pointer to a label */
125   int condition;   /* true or false ifx */
126   int generated;   /* set true when the code associated with the ifx
127                     * is generated */
128 } resolvedIfx;
129
130 extern int pic16_ptrRegReq ;
131 extern int pic16_nRegs;
132 extern FILE *codeOutFile;
133 static void saverbank (int, iCode *,bool);
134
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
137
138 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
139 0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
142
143 static  pBlock *pb;
144
145 /*-----------------------------------------------------------------*/
146 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
147 /*                 exponent of 2 is returned, otherwise -1 is      */
148 /*                 returned.                                       */
149 /* note that this is similar to the function `powof2' in SDCCsymt  */
150 /* if(n == 2^y)                                                    */
151 /*   return y;                                                     */
152 /* return -1;                                                      */
153 /*-----------------------------------------------------------------*/
154 static int my_powof2 (unsigned long num)
155 {
156   if(num) {
157     if( (num & (num-1)) == 0) {
158       int nshifts = -1;
159       while(num) {
160         num>>=1;
161         nshifts++;
162       }
163       return nshifts;
164     }
165   }
166
167   return -1;
168 }
169
170 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
171 {
172
173   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
174                        line_no,
175                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
176                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
177                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
178                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
179                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
180                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
181                        ((result) ? AOP_SIZE(result) : 0));
182
183 }
184
185 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
186 {
187
188   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
189                        line_no,
190                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
191                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
192                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
193                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
194                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
195                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
196
197 }
198
199 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
200 {
201     va_list ap;
202     char lb[INITIAL_INLINEASM];  
203     char *lbp = lb;
204
205     if(!pic16_debug_verbose)
206       return;
207
208     va_start(ap,fmt);   
209
210     if (inst && *inst) {
211         if (fmt && *fmt)
212             sprintf(lb,"%s\t",inst);
213         else
214             sprintf(lb,"%s",inst);
215         vsprintf(lb+(strlen(lb)),fmt,ap);
216     }  else
217         vsprintf(lb,fmt,ap);
218
219     while (isspace(*lbp)) lbp++;
220
221     if (lbp && *lbp) 
222         lineCurr = (lineCurr ?
223                     connectLine(lineCurr,newLineNode(lb)) :
224                     (lineHead = newLineNode(lb)));
225     lineCurr->isInline = _G.inLine;
226     lineCurr->isDebug  = _G.debugLine;
227
228     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
229
230     va_end(ap);
231 }
232
233
234 void pic16_emitpLabel(int key)
235 {
236   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
237 }
238
239 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
240 {
241
242   if(pcop)
243     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
244   else
245     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
246 }
247
248 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
249 {
250
251   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
252
253 }
254
255 /*-----------------------------------------------------------------*/
256 /* pic16_emitcode - writes the code into a file : for now it is simple    */
257 /*-----------------------------------------------------------------*/
258 void pic16_emitcode (char *inst,char *fmt, ...)
259 {
260     va_list ap;
261     char lb[INITIAL_INLINEASM];  
262     char *lbp = lb;
263
264     va_start(ap,fmt);   
265
266     if (inst && *inst) {
267         if (fmt && *fmt)
268             sprintf(lb,"%s\t",inst);
269         else
270             sprintf(lb,"%s",inst);
271         vsprintf(lb+(strlen(lb)),fmt,ap);
272     }  else
273         vsprintf(lb,fmt,ap);
274
275     while (isspace(*lbp)) lbp++;
276
277     if (lbp && *lbp) 
278         lineCurr = (lineCurr ?
279                     connectLine(lineCurr,newLineNode(lb)) :
280                     (lineHead = newLineNode(lb)));
281     lineCurr->isInline = _G.inLine;
282     lineCurr->isDebug  = _G.debugLine;
283
284     if(pic16_debug_verbose)
285       pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
286
287     va_end(ap);
288 }
289
290
291 /*-----------------------------------------------------------------*/
292 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
293 /*-----------------------------------------------------------------*/
294 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
295 {
296     bool r0iu = FALSE , r1iu = FALSE;
297     bool r0ou = FALSE , r1ou = FALSE;
298
299     /* the logic: if r0 & r1 used in the instruction
300     then we are in trouble otherwise */
301
302     /* first check if r0 & r1 are used by this
303     instruction, in which case we are in trouble */
304     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
305         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
306     {
307         goto endOfWorld;      
308     }
309
310     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
311     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
312
313     /* if no usage of r0 then return it */
314     if (!r0iu && !r0ou) {
315         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
316         (*aopp)->type = AOP_R0;
317         
318         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
319     }
320
321     /* if no usage of r1 then return it */
322     if (!r1iu && !r1ou) {
323         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
324         (*aopp)->type = AOP_R1;
325
326         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
327     }    
328
329     /* now we know they both have usage */
330     /* if r0 not used in this instruction */
331     if (!r0iu) {
332         /* push it if not already pushed */
333         if (!_G.r0Pushed) {
334           //pic16_emitcode ("push","%s",
335           //          pic16_regWithIdx(R0_IDX)->dname);
336             _G.r0Pushed++ ;
337         }
338         
339         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
340         (*aopp)->type = AOP_R0;
341
342         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
343     }
344
345     /* if r1 not used then */
346
347     if (!r1iu) {
348         /* push it if not already pushed */
349         if (!_G.r1Pushed) {
350           //pic16_emitcode ("push","%s",
351           //          pic16_regWithIdx(R1_IDX)->dname);
352             _G.r1Pushed++ ;
353         }
354         
355         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
356         (*aopp)->type = AOP_R1;
357         return pic16_regWithIdx(R1_IDX);
358     }
359
360 endOfWorld :
361     /* I said end of world but not quite end of world yet */
362     /* if this is a result then we can push it on the stack*/
363     if (result) {
364         (*aopp)->type = AOP_STK;    
365         return NULL;
366     }
367
368     /* other wise this is true end of the world */
369     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
370            "getFreePtr should never reach here");
371     exit(0);
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* newAsmop - creates a new asmOp                                  */
376 /*-----------------------------------------------------------------*/
377 static asmop *newAsmop (short type)
378 {
379     asmop *aop;
380
381     aop = Safe_calloc(1,sizeof(asmop));
382     aop->type = type;
383     return aop;
384 }
385
386 static void genSetDPTR(int n)
387 {
388     if (!n)
389     {
390         pic16_emitcode(";", "Select standard DPTR");
391         pic16_emitcode("mov", "dps, #0x00");
392     }
393     else
394     {
395         pic16_emitcode(";", "Select alternate DPTR");
396         pic16_emitcode("mov", "dps, #0x01");
397     }
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* resolveIfx - converts an iCode ifx into a form more useful for  */
402 /*              generating code                                    */
403 /*-----------------------------------------------------------------*/
404 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
405 {
406   if(!resIfx) 
407     return;
408
409   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
410
411   resIfx->condition = 1;    /* assume that the ifx is true */
412   resIfx->generated = 0;    /* indicate that the ifx has not been used */
413
414   if(!ifx) {
415     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
416 /*
417     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
418                         __FUNCTION__,__LINE__,resIfx->lbl->key);
419 */
420   } else {
421     if(IC_TRUE(ifx)) {
422       resIfx->lbl = IC_TRUE(ifx);
423     } else {
424       resIfx->lbl = IC_FALSE(ifx);
425       resIfx->condition = 0;
426     }
427 /*
428     if(IC_TRUE(ifx)) 
429       DEBUGpic16_emitcode("; ***","ifx true is non-null");
430     if(IC_FALSE(ifx)) 
431       DEBUGpic16_emitcode("; ***","ifx false is non-null");
432 */
433   }
434
435   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
436
437 }
438 /*-----------------------------------------------------------------*/
439 /* pointerCode - returns the code for a pointer type               */
440 /*-----------------------------------------------------------------*/
441 static int pointerCode (sym_link *etype)
442 {
443
444     return PTR_TYPE(SPEC_OCLS(etype));
445
446 }
447
448 /*-----------------------------------------------------------------*/
449 /* aopForSym - for a true symbol                                   */
450 /*-----------------------------------------------------------------*/
451 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
452 {
453     asmop *aop;
454     memmap *space= SPEC_OCLS(sym->etype);
455
456     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
457     /* if already has one */
458     if (sym->aop)
459         return sym->aop;
460
461     /* assign depending on the storage class */
462     /* if it is on the stack or indirectly addressable */
463     /* space we need to assign either r0 or r1 to it   */    
464     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
465         sym->aop = aop = newAsmop(0);
466         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
467         aop->size = getSize(sym->type);
468
469         /* now assign the address of the variable to 
470         the pointer register */
471         if (aop->type != AOP_STK) {
472
473             if (sym->onStack) {
474                     if ( _G.accInUse )
475                         pic16_emitcode("push","acc");
476
477                     pic16_emitcode("mov","a,_bp");
478                     pic16_emitcode("add","a,#0x%02x",
479                              ((sym->stack < 0) ?
480                               ((char)(sym->stack - _G.nRegsSaved )) :
481                               ((char)sym->stack)) & 0xff);
482                     pic16_emitcode("mov","%s,a",
483                              aop->aopu.aop_ptr->name);
484
485                     if ( _G.accInUse )
486                         pic16_emitcode("pop","acc");
487             } else
488                 pic16_emitcode("mov","%s,#%s",
489                          aop->aopu.aop_ptr->name,
490                          sym->rname);
491             aop->paged = space->paged;
492         } else
493             aop->aopu.aop_stk = sym->stack;
494         return aop;
495     }
496     
497     if (sym->onStack && options.stack10bit)
498     {
499         /* It's on the 10 bit stack, which is located in
500          * far data space.
501          */
502          
503       //DEBUGpic16_emitcode(";","%d",__LINE__);
504
505         if ( _G.accInUse )
506                 pic16_emitcode("push","acc");
507
508         pic16_emitcode("mov","a,_bp");
509         pic16_emitcode("add","a,#0x%02x",
510                  ((sym->stack < 0) ?
511                    ((char)(sym->stack - _G.nRegsSaved )) :
512                    ((char)sym->stack)) & 0xff);
513         
514         genSetDPTR(1);
515         pic16_emitcode ("mov","dpx1,#0x40");
516         pic16_emitcode ("mov","dph1,#0x00");
517         pic16_emitcode ("mov","dpl1, a");
518         genSetDPTR(0);
519         
520         if ( _G.accInUse )
521             pic16_emitcode("pop","acc");
522             
523         sym->aop = aop = newAsmop(AOP_DPTR2);
524         aop->size = getSize(sym->type); 
525         return aop;
526     }
527
528     //DEBUGpic16_emitcode(";","%d",__LINE__);
529     /* if in bit space */
530     if (IN_BITSPACE(space)) {
531         sym->aop = aop = newAsmop (AOP_CRY);
532         aop->aopu.aop_dir = sym->rname ;
533         aop->size = getSize(sym->type);
534         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
535         return aop;
536     }
537     /* if it is in direct space */
538     if (IN_DIRSPACE(space)) {
539         sym->aop = aop = newAsmop (AOP_DIR);
540         aop->aopu.aop_dir = sym->rname ;
541         aop->size = getSize(sym->type);
542         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
543         return aop;
544     }
545
546     /* special case for a function */
547     if (IS_FUNC(sym->type)) {   
548         sym->aop = aop = newAsmop(AOP_IMMD);    
549         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
550         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
551         strcpy(aop->aopu.aop_immd,sym->rname);
552         aop->size = FPTRSIZE; 
553         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
554         return aop;
555     }
556
557
558     /* only remaining is far space */
559     /* in which case DPTR gets the address */
560     sym->aop = aop = newAsmop(AOP_PCODE);
561
562     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
563     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
564     PCOI(aop->aopu.pcop)->index = 0;
565
566     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
567                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
568
569     pic16_allocDirReg (IC_LEFT(ic));
570
571     aop->size = FPTRSIZE; 
572 /*
573     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
574     sym->aop = aop = newAsmop(AOP_DPTR);
575     pic16_emitcode ("mov","dptr,#%s", sym->rname);
576     aop->size = getSize(sym->type);
577
578     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
579 */
580
581     /* if it is in code space */
582     if (IN_CODESPACE(space))
583         aop->code = 1;
584
585     return aop;     
586 }
587
588 /*-----------------------------------------------------------------*/
589 /* aopForRemat - rematerialzes an object                           */
590 /*-----------------------------------------------------------------*/
591 static asmop *aopForRemat (operand *op) // x symbol *sym)
592 {
593   symbol *sym = OP_SYMBOL(op);
594   iCode *ic = NULL;
595   asmop *aop = newAsmop(AOP_PCODE);
596   int val = 0;
597   int offset = 0;
598
599   ic = sym->rematiCode;
600
601   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
602   if(IS_OP_POINTER(op)) {
603     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
604   }
605   for (;;) {
606     if (ic->op == '+') {
607       val += (int) operandLitValue(IC_RIGHT(ic));
608     } else if (ic->op == '-') {
609       val -= (int) operandLitValue(IC_RIGHT(ic));
610     } else
611       break;
612         
613     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
614   }
615
616   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
617   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
618   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
619   PCOI(aop->aopu.pcop)->index = val;
620
621   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
622                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
623                       val, IS_PTR_CONST(operandType(op)));
624
625   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
626
627   pic16_allocDirReg (IC_LEFT(ic));
628
629   return aop;        
630 }
631
632 static int aopIdx (asmop *aop, int offset)
633 {
634   if(!aop)
635     return -1;
636
637   if(aop->type !=  AOP_REG)
638     return -2;
639         
640   return aop->aopu.aop_reg[offset]->rIdx;
641
642 }
643 /*-----------------------------------------------------------------*/
644 /* regsInCommon - two operands have some registers in common       */
645 /*-----------------------------------------------------------------*/
646 static bool regsInCommon (operand *op1, operand *op2)
647 {
648     symbol *sym1, *sym2;
649     int i;
650
651     /* if they have registers in common */
652     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
653         return FALSE ;
654
655     sym1 = OP_SYMBOL(op1);
656     sym2 = OP_SYMBOL(op2);
657
658     if (sym1->nRegs == 0 || sym2->nRegs == 0)
659         return FALSE ;
660
661     for (i = 0 ; i < sym1->nRegs ; i++) {
662         int j;
663         if (!sym1->regs[i])
664             continue ;
665
666         for (j = 0 ; j < sym2->nRegs ;j++ ) {
667             if (!sym2->regs[j])
668                 continue ;
669
670             if (sym2->regs[j] == sym1->regs[i])
671                 return TRUE ;
672         }
673     }
674
675     return FALSE ;
676 }
677
678 /*-----------------------------------------------------------------*/
679 /* operandsEqu - equivalent                                        */
680 /*-----------------------------------------------------------------*/
681 static bool operandsEqu ( operand *op1, operand *op2)
682 {
683     symbol *sym1, *sym2;
684
685     /* if they not symbols */
686     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
687         return FALSE;
688
689     sym1 = OP_SYMBOL(op1);
690     sym2 = OP_SYMBOL(op2);
691
692     /* if both are itemps & one is spilt
693        and the other is not then false */
694     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
695         sym1->isspilt != sym2->isspilt )
696         return FALSE ;
697
698     /* if they are the same */
699     if (sym1 == sym2)
700         return TRUE ;
701
702     if (strcmp(sym1->rname,sym2->rname) == 0)
703         return TRUE;
704
705
706     /* if left is a tmp & right is not */
707     if (IS_ITEMP(op1)  && 
708         !IS_ITEMP(op2) &&
709         sym1->isspilt  &&
710         (sym1->usl.spillLoc == sym2))
711         return TRUE;
712
713     if (IS_ITEMP(op2)  && 
714         !IS_ITEMP(op1) &&
715         sym2->isspilt  &&
716         sym1->level > 0 &&
717         (sym2->usl.spillLoc == sym1))
718         return TRUE ;
719
720     return FALSE ;
721 }
722
723 /*-----------------------------------------------------------------*/
724 /* pic16_sameRegs - two asmops have the same registers                   */
725 /*-----------------------------------------------------------------*/
726 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
727 {
728     int i;
729
730     if (aop1 == aop2)
731         return TRUE ;
732
733     if (aop1->type != AOP_REG ||
734         aop2->type != AOP_REG )
735         return FALSE ;
736
737     if (aop1->size != aop2->size )
738         return FALSE ;
739
740     for (i = 0 ; i < aop1->size ; i++ )
741         if (aop1->aopu.aop_reg[i] !=
742             aop2->aopu.aop_reg[i] )
743             return FALSE ;
744
745     return TRUE ;
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* pic16_aopOp - allocates an asmop for an operand  :                    */
750 /*-----------------------------------------------------------------*/
751 void pic16_aopOp (operand *op, iCode *ic, bool result)
752 {
753     asmop *aop;
754     symbol *sym;
755     int i;
756
757     if (!op)
758         return ;
759
760     //    DEBUGpic16_emitcode(";","%d",__LINE__);
761     /* if this a literal */
762     if (IS_OP_LITERAL(op)) {
763         op->aop = aop = newAsmop(AOP_LIT);
764         aop->aopu.aop_lit = op->operand.valOperand;
765         aop->size = getSize(operandType(op));
766         return;
767     }
768
769     {
770       sym_link *type = operandType(op);
771       if(IS_PTR_CONST(type))
772         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
773     }
774
775     /* if already has a asmop then continue */
776     if (op->aop)
777         return ;
778
779     /* if the underlying symbol has a aop */
780     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
781       DEBUGpic16_emitcode(";","%d",__LINE__);
782         op->aop = OP_SYMBOL(op)->aop;
783         return;
784     }
785
786     /* if this is a true symbol */
787     if (IS_TRUE_SYMOP(op)) {    
788       //DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
789       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
790       return ;
791     }
792
793     /* this is a temporary : this has
794     only four choices :
795     a) register
796     b) spillocation
797     c) rematerialize 
798     d) conditional   
799     e) can be a return use only */
800
801     sym = OP_SYMBOL(op);
802
803
804     /* if the type is a conditional */
805     if (sym->regType == REG_CND) {
806         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
807         aop->size = 0;
808         return;
809     }
810
811     /* if it is spilt then two situations
812     a) is rematerialize 
813     b) has a spill location */
814     if (sym->isspilt || sym->nRegs == 0) {
815
816       DEBUGpic16_emitcode(";","%d",__LINE__);
817         /* rematerialize it NOW */
818         if (sym->remat) {
819
820             sym->aop = op->aop = aop =
821                                       aopForRemat (op);
822             aop->size = getSize(sym->type);
823             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
824             return;
825         }
826
827         if (sym->accuse) {
828             int i;
829             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830             aop->size = getSize(sym->type);
831             for ( i = 0 ; i < 2 ; i++ )
832                 aop->aopu.aop_str[i] = accUse[i];
833             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
834             return;  
835         }
836
837         if (sym->ruonly ) {
838           /*
839           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
840           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
841           //pic16_allocDirReg (IC_LEFT(ic));
842           aop->size = getSize(sym->type);
843           */
844
845           unsigned i;
846
847           aop = op->aop = sym->aop = newAsmop(AOP_STR);
848           aop->size = getSize(sym->type);
849           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
850             aop->aopu.aop_str[i] = fReturn[i];
851
852           DEBUGpic16_emitcode(";","%d",__LINE__);
853           return;
854         }
855
856         /* else spill location  */
857         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
858             /* force a new aop if sizes differ */
859             sym->usl.spillLoc->aop = NULL;
860         }
861         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
862                             __FUNCTION__,__LINE__,
863                             sym->usl.spillLoc->rname,
864                             sym->rname, sym->usl.spillLoc->offset);
865
866         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
867         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
868         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
869                                           getSize(sym->type), 
870                                           sym->usl.spillLoc->offset);
871         aop->size = getSize(sym->type);
872
873         return;
874     }
875
876     {
877       sym_link *type = operandType(op);
878       if(IS_PTR_CONST(type)) 
879         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
880     }
881
882     /* must be in a register */
883     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
884     sym->aop = op->aop = aop = newAsmop(AOP_REG);
885     aop->size = sym->nRegs;
886     for ( i = 0 ; i < sym->nRegs ;i++)
887         aop->aopu.aop_reg[i] = sym->regs[i];
888 }
889
890 /*-----------------------------------------------------------------*/
891 /* pic16_freeAsmop - free up the asmop given to an operand               */
892 /*----------------------------------------------------------------*/
893 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
894 {   
895     asmop *aop ;
896
897     if (!op)
898         aop = aaop;
899     else 
900         aop = op->aop;
901
902     if (!aop)
903         return ;
904
905     if (aop->freed)
906         goto dealloc; 
907
908     aop->freed = 1;
909
910     /* depending on the asmop type only three cases need work AOP_RO
911        , AOP_R1 && AOP_STK */
912 #if 0
913     switch (aop->type) {
914         case AOP_R0 :
915             if (_G.r0Pushed ) {
916                 if (pop) {
917                     pic16_emitcode ("pop","ar0");     
918                     _G.r0Pushed--;
919                 }
920             }
921             bitVectUnSetBit(ic->rUsed,R0_IDX);
922             break;
923
924         case AOP_R1 :
925             if (_G.r1Pushed ) {
926                 if (pop) {
927                     pic16_emitcode ("pop","ar1");
928                     _G.r1Pushed--;
929                 }
930             }
931             bitVectUnSetBit(ic->rUsed,R1_IDX);          
932             break;
933
934         case AOP_STK :
935         {
936             int sz = aop->size;    
937             int stk = aop->aopu.aop_stk + aop->size;
938             bitVectUnSetBit(ic->rUsed,R0_IDX);
939             bitVectUnSetBit(ic->rUsed,R1_IDX);          
940
941             getFreePtr(ic,&aop,FALSE);
942             
943             if (options.stack10bit)
944             {
945                 /* I'm not sure what to do here yet... */
946                 /* #STUB */
947                 fprintf(stderr, 
948                         "*** Warning: probably generating bad code for "
949                         "10 bit stack mode.\n");
950             }
951             
952             if (stk) {
953                 pic16_emitcode ("mov","a,_bp");
954                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
955                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
956             } else {
957                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
958             }
959
960             while (sz--) {
961                 pic16_emitcode("pop","acc");
962                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
963                 if (!sz) break;
964                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
965             }
966             op->aop = aop;
967             pic16_freeAsmop(op,NULL,ic,TRUE);
968             if (_G.r0Pushed) {
969                 pic16_emitcode("pop","ar0");
970                 _G.r0Pushed--;
971             }
972
973             if (_G.r1Pushed) {
974                 pic16_emitcode("pop","ar1");
975                 _G.r1Pushed--;
976             }       
977         }
978     }
979 #endif
980
981 dealloc:
982     /* all other cases just dealloc */
983     if (op ) {
984         op->aop = NULL;
985         if (IS_SYMOP(op)) {
986             OP_SYMBOL(op)->aop = NULL;    
987             /* if the symbol has a spill */
988             if (SPIL_LOC(op))
989                 SPIL_LOC(op)->aop = NULL;
990         }
991     }
992 }
993
994 /*-----------------------------------------------------------------*/
995 /* pic16_aopGet - for fetching value of the aop                          */
996 /*-----------------------------------------------------------------*/
997 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
998 {
999     char *s = buffer ;
1000     char *rs;
1001
1002     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1003     /* offset is greater than
1004     size then zero */
1005     if (offset > (aop->size - 1) &&
1006         aop->type != AOP_LIT)
1007         return zero;
1008
1009     /* depending on type */
1010     switch (aop->type) {
1011         
1012     case AOP_R0:
1013     case AOP_R1:
1014         DEBUGpic16_emitcode(";","%d",__LINE__);
1015         /* if we need to increment it */       
1016         while (offset > aop->coff) {        
1017             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1018             aop->coff++;
1019         }
1020         
1021         while (offset < aop->coff) {
1022             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1023             aop->coff--;
1024         }
1025         
1026         aop->coff = offset ;
1027         if (aop->paged) {
1028             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1029             return (dname ? "acc" : "a");
1030         }       
1031         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1032         rs = Safe_calloc(1,strlen(s)+1);
1033         strcpy(rs,s);   
1034         return rs;
1035         
1036     case AOP_DPTR:
1037     case AOP_DPTR2:
1038         DEBUGpic16_emitcode(";","%d",__LINE__);
1039     if (aop->type == AOP_DPTR2)
1040     {
1041         genSetDPTR(1);
1042     }
1043     
1044         while (offset > aop->coff) {
1045             pic16_emitcode ("inc","dptr");
1046             aop->coff++;
1047         }
1048         
1049         while (offset < aop->coff) {        
1050             pic16_emitcode("lcall","__decdptr");
1051             aop->coff--;
1052         }
1053         
1054         aop->coff = offset;
1055         if (aop->code) {
1056             pic16_emitcode("clr","a");
1057             pic16_emitcode("movc","a,@a+dptr");
1058         }
1059     else {
1060             pic16_emitcode("movx","a,@dptr");
1061     }
1062             
1063     if (aop->type == AOP_DPTR2)
1064     {
1065         genSetDPTR(0);
1066     }
1067             
1068     return (dname ? "acc" : "a");
1069         
1070         
1071     case AOP_IMMD:
1072         if (bit16) 
1073             sprintf (s,"%s",aop->aopu.aop_immd);
1074         else
1075             if (offset) 
1076                 sprintf(s,"(%s >> %d)",
1077                         aop->aopu.aop_immd,
1078                         offset*8);
1079             else
1080                 sprintf(s,"%s",
1081                         aop->aopu.aop_immd);
1082         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1083         rs = Safe_calloc(1,strlen(s)+1);
1084         strcpy(rs,s);   
1085         return rs;
1086         
1087     case AOP_DIR:
1088       if (offset) {
1089         sprintf(s,"(%s + %d)",
1090                 aop->aopu.aop_dir,
1091                 offset);
1092         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1093       } else
1094             sprintf(s,"%s",aop->aopu.aop_dir);
1095         rs = Safe_calloc(1,strlen(s)+1);
1096         strcpy(rs,s);   
1097         return rs;
1098         
1099     case AOP_REG:
1100       //if (dname) 
1101       //    return aop->aopu.aop_reg[offset]->dname;
1102       //else
1103             return aop->aopu.aop_reg[offset]->name;
1104         
1105     case AOP_CRY:
1106       //pic16_emitcode(";","%d",__LINE__);
1107       return aop->aopu.aop_dir;
1108         
1109     case AOP_ACC:
1110         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1111         return "AOP_accumulator_bug";
1112
1113     case AOP_LIT:
1114         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1115         rs = Safe_calloc(1,strlen(s)+1);
1116         strcpy(rs,s);   
1117         return rs;
1118         
1119     case AOP_STR:
1120         aop->coff = offset ;
1121         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1122             dname)
1123             return "acc";
1124         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1125         
1126         return aop->aopu.aop_str[offset];
1127         
1128     case AOP_PCODE:
1129       {
1130         pCodeOp *pcop = aop->aopu.pcop;
1131         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1132         if(pcop->name) {
1133           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1134           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1135           sprintf(s,"%s", pcop->name);
1136         } else
1137           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1138
1139       }
1140       rs = Safe_calloc(1,strlen(s)+1);
1141       strcpy(rs,s);   
1142       return rs;
1143
1144     }
1145
1146     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1147            "aopget got unsupported aop->type");
1148     exit(0);
1149 }
1150
1151
1152 /*-----------------------------------------------------------------*/
1153 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1154 /*-----------------------------------------------------------------*/
1155 pCodeOp *pic16_popGetTempReg(void)
1156 {
1157
1158   pCodeOp *pcop;
1159
1160   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1161   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1162     PCOR(pcop)->r->wasUsed=1;
1163     PCOR(pcop)->r->isFree=0;
1164   }
1165
1166   return pcop;
1167 }
1168
1169 /*-----------------------------------------------------------------*/
1170 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1171 /*-----------------------------------------------------------------*/
1172 void pic16_popReleaseTempReg(pCodeOp *pcop)
1173 {
1174
1175   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1176     PCOR(pcop)->r->isFree = 1;
1177
1178 }
1179 /*-----------------------------------------------------------------*/
1180 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1181 /*-----------------------------------------------------------------*/
1182 pCodeOp *pic16_popGetLabel(unsigned int key)
1183 {
1184
1185   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1186
1187   if(key>max_key)
1188     max_key = key;
1189
1190   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1191 }
1192
1193 /*-----------------------------------------------------------------*/
1194 /* pic16_popCopyReg - copy a pcode operator                              */
1195 /*-----------------------------------------------------------------*/
1196 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1197 {
1198   pCodeOpReg *pcor;
1199
1200   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1201   pcor->pcop.type = pc->pcop.type;
1202   if(pc->pcop.name) {
1203     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1204       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1205   } else
1206     pcor->pcop.name = NULL;
1207
1208   pcor->r = pc->r;
1209   pcor->rIdx = pc->rIdx;
1210   pcor->r->wasUsed=1;
1211
1212   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1213
1214   return PCOP(pcor);
1215 }
1216 /*-----------------------------------------------------------------*/
1217 /* pic16_popGet - asm operator to pcode operator conversion              */
1218 /*-----------------------------------------------------------------*/
1219 pCodeOp *pic16_popGetLit(unsigned int lit)
1220 {
1221
1222   return pic16_newpCodeOpLit(lit);
1223 }
1224
1225
1226 /*-----------------------------------------------------------------*/
1227 /* pic16_popGetImmd - asm operator to pcode immediate conversion         */
1228 /*-----------------------------------------------------------------*/
1229 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1230 {
1231
1232   return pic16_newpCodeOpImmd(name, offset,index, 0);
1233 }
1234
1235
1236 /*-----------------------------------------------------------------*/
1237 /* pic16_popGet - asm operator to pcode operator conversion              */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *pic16_popGetWithString(char *str)
1240 {
1241   pCodeOp *pcop;
1242
1243
1244   if(!str) {
1245     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1246     exit (1);
1247   }
1248
1249   pcop = pic16_newpCodeOp(str,PO_STR);
1250
1251   return pcop;
1252 }
1253
1254 /*-----------------------------------------------------------------*/
1255 /* popRegFromString -                                              */
1256 /*-----------------------------------------------------------------*/
1257 static pCodeOp *popRegFromString(char *str, int size, int offset)
1258 {
1259
1260   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1261   pcop->type = PO_DIR;
1262
1263   DEBUGpic16_emitcode(";","%d",__LINE__);
1264
1265   if(!str)
1266     str = "BAD_STRING";
1267
1268   pcop->name = Safe_calloc(1,strlen(str)+1);
1269   strcpy(pcop->name,str);
1270
1271   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1272
1273   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1274   if(PCOR(pcop)->r == NULL) {
1275     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1276     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1277     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1278   } else {
1279     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1280   }
1281   PCOR(pcop)->instance = offset;
1282
1283   return pcop;
1284 }
1285
1286 static pCodeOp *popRegFromIdx(int rIdx)
1287 {
1288   pCodeOp *pcop;
1289
1290   DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1291                        __FUNCTION__,__LINE__,rIdx);
1292
1293   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1294
1295   PCOR(pcop)->rIdx = rIdx;
1296   PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1297   PCOR(pcop)->r->isFree = 0;
1298   PCOR(pcop)->r->wasUsed = 1;
1299
1300   pcop->type = PCOR(pcop)->r->pc_type;
1301
1302
1303   return pcop;
1304 }
1305 /*-----------------------------------------------------------------*/
1306 /* pic16_popGet - asm operator to pcode operator conversion              */
1307 /*-----------------------------------------------------------------*/
1308 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1309 {
1310   //char *s = buffer ;
1311     //char *rs;
1312
1313     pCodeOp *pcop;
1314
1315     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1316     /* offset is greater than
1317     size then zero */
1318
1319     if (offset > (aop->size - 1) &&
1320         aop->type != AOP_LIT)
1321       return NULL;  //zero;
1322
1323     /* depending on type */
1324     switch (aop->type) {
1325         
1326     case AOP_R0:
1327     case AOP_R1:
1328     case AOP_DPTR:
1329     case AOP_DPTR2:
1330     case AOP_ACC:
1331         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1332         return NULL;
1333         
1334     case AOP_IMMD:
1335       DEBUGpic16_emitcode(";","%d",__LINE__);
1336       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1337
1338     case AOP_DIR:
1339       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1340 #if 0
1341         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1342         pcop->type = PO_DIR;
1343
1344         /*
1345         if (offset)
1346             sprintf(s,"(%s + %d)",
1347                     aop->aopu.aop_dir,
1348                     offset);
1349         else
1350             sprintf(s,"%s",aop->aopu.aop_dir);
1351         pcop->name = Safe_calloc(1,strlen(s)+1);
1352         strcpy(pcop->name,s);   
1353         */
1354         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1355         strcpy(pcop->name,aop->aopu.aop_dir);   
1356         PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1357         if(PCOR(pcop)->r == NULL) {
1358           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1359           PCOR(pcop)->r = pic16_allocRegByName (aop->aopu.aop_dir,aop->size);
1360           DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1361         } else {
1362           DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1363         }
1364         PCOR(pcop)->instance = offset;
1365
1366         return pcop;
1367 #endif
1368         
1369     case AOP_REG:
1370       {
1371         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1372
1373         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1374         PCOR(pcop)->rIdx = rIdx;
1375         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1376         PCOR(pcop)->r->wasUsed=1;
1377         PCOR(pcop)->r->isFree=0;
1378
1379         PCOR(pcop)->instance = offset;
1380         pcop->type = PCOR(pcop)->r->pc_type;
1381         //rs = aop->aopu.aop_reg[offset]->name;
1382         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1383         return pcop;
1384       }
1385
1386     case AOP_CRY:
1387       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1388       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1389       //if(PCOR(pcop)->r == NULL)
1390       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1391       return pcop;
1392         
1393     case AOP_LIT:
1394       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1395
1396     case AOP_STR:
1397       DEBUGpic16_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1398       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1399       /*
1400       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1401       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1402       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1403       pcop->type = PCOR(pcop)->r->pc_type;
1404       pcop->name = PCOR(pcop)->r->name;
1405
1406       return pcop;
1407       */
1408
1409     case AOP_PCODE:
1410       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1411                           __LINE__, 
1412                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1413       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1414       PCOI(pcop)->offset = offset;
1415       return pcop;
1416     }
1417
1418     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1419            "pic16_popGet got unsupported aop->type");
1420     exit(0);
1421 }
1422 /*-----------------------------------------------------------------*/
1423 /* pic16_aopPut - puts a string for a aop                                */
1424 /*-----------------------------------------------------------------*/
1425 void pic16_aopPut (asmop *aop, char *s, int offset)
1426 {
1427     char *d = buffer ;
1428     symbol *lbl ;
1429
1430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1431
1432     if (aop->size && offset > ( aop->size - 1)) {
1433         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1434                "pic16_aopPut got offset > aop->size");
1435         exit(0);
1436     }
1437
1438     /* will assign value to value */
1439     /* depending on where it is ofcourse */
1440     switch (aop->type) {
1441     case AOP_DIR:
1442       if (offset) {
1443         sprintf(d,"(%s + %d)",
1444                 aop->aopu.aop_dir,offset);
1445         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1446
1447       } else
1448             sprintf(d,"%s",aop->aopu.aop_dir);
1449         
1450         if (strcmp(d,s)) {
1451           DEBUGpic16_emitcode(";","%d",__LINE__);
1452           if(strcmp(s,"W"))
1453             pic16_emitcode("movf","%s,w",s);
1454           pic16_emitcode("movwf","%s",d);
1455
1456           if(strcmp(s,"W")) {
1457             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1458             if(offset >= aop->size) {
1459               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1460               break;
1461             } else
1462               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1463           }
1464
1465           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1466
1467
1468         }
1469         break;
1470         
1471     case AOP_REG:
1472       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1473         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1474           /*
1475             if (*s == '@'           ||
1476                 strcmp(s,"r0") == 0 ||
1477                 strcmp(s,"r1") == 0 ||
1478                 strcmp(s,"r2") == 0 ||
1479                 strcmp(s,"r3") == 0 ||
1480                 strcmp(s,"r4") == 0 ||
1481                 strcmp(s,"r5") == 0 ||
1482                 strcmp(s,"r6") == 0 || 
1483                 strcmp(s,"r7") == 0 )
1484                 pic16_emitcode("mov","%s,%s  ; %d",
1485                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1486             else
1487           */
1488
1489           if(strcmp(s,"W")==0 )
1490             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1491
1492           pic16_emitcode("movwf","%s",
1493                    aop->aopu.aop_reg[offset]->name);
1494
1495           if(strcmp(s,zero)==0) {
1496             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1497
1498           } else if(strcmp(s,"W")==0) {
1499             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500             pcop->type = PO_GPR_REGISTER;
1501
1502             PCOR(pcop)->rIdx = -1;
1503             PCOR(pcop)->r = NULL;
1504
1505             DEBUGpic16_emitcode(";","%d",__LINE__);
1506             pcop->name = Safe_strdup(s);
1507             pic16_emitpcode(POC_MOVFW,pcop);
1508             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1509           } else if(strcmp(s,one)==0) {
1510             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1511             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1512           } else {
1513             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1514           }
1515         }
1516         break;
1517         
1518     case AOP_DPTR:
1519     case AOP_DPTR2:
1520     
1521     if (aop->type == AOP_DPTR2)
1522     {
1523         genSetDPTR(1);
1524     }
1525     
1526         if (aop->code) {
1527             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1528                    "pic16_aopPut writting to code space");
1529             exit(0);
1530         }
1531         
1532         while (offset > aop->coff) {
1533             aop->coff++;
1534             pic16_emitcode ("inc","dptr");
1535         }
1536         
1537         while (offset < aop->coff) {
1538             aop->coff-- ;
1539             pic16_emitcode("lcall","__decdptr");
1540         }
1541         
1542         aop->coff = offset;
1543         
1544         /* if not in accumulater */
1545         MOVA(s);        
1546         
1547         pic16_emitcode ("movx","@dptr,a");
1548         
1549     if (aop->type == AOP_DPTR2)
1550     {
1551         genSetDPTR(0);
1552     }
1553         break;
1554         
1555     case AOP_R0:
1556     case AOP_R1:
1557         while (offset > aop->coff) {
1558             aop->coff++;
1559             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1560         }
1561         while (offset < aop->coff) {
1562             aop->coff-- ;
1563             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1564         }
1565         aop->coff = offset;
1566         
1567         if (aop->paged) {
1568             MOVA(s);           
1569             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1570             
1571         } else
1572             if (*s == '@') {
1573                 MOVA(s);
1574                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1575             } else
1576                 if (strcmp(s,"r0") == 0 ||
1577                     strcmp(s,"r1") == 0 ||
1578                     strcmp(s,"r2") == 0 ||
1579                     strcmp(s,"r3") == 0 ||
1580                     strcmp(s,"r4") == 0 ||
1581                     strcmp(s,"r5") == 0 ||
1582                     strcmp(s,"r6") == 0 || 
1583                     strcmp(s,"r7") == 0 ) {
1584                     char buffer[10];
1585                     sprintf(buffer,"a%s",s);
1586                     pic16_emitcode("mov","@%s,%s",
1587                              aop->aopu.aop_ptr->name,buffer);
1588                 } else
1589                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1590         
1591         break;
1592         
1593     case AOP_STK:
1594         if (strcmp(s,"a") == 0)
1595             pic16_emitcode("push","acc");
1596         else
1597             pic16_emitcode("push","%s",s);
1598         
1599         break;
1600         
1601     case AOP_CRY:
1602         /* if bit variable */
1603         if (!aop->aopu.aop_dir) {
1604             pic16_emitcode("clr","a");
1605             pic16_emitcode("rlc","a");
1606         } else {
1607             if (s == zero) 
1608                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1609             else
1610                 if (s == one)
1611                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1612                 else
1613                     if (!strcmp(s,"c"))
1614                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1615                     else {
1616                         lbl = newiTempLabel(NULL);
1617                         
1618                         if (strcmp(s,"a")) {
1619                             MOVA(s);
1620                         }
1621                         pic16_emitcode("clr","c");
1622                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1623                         pic16_emitcode("cpl","c");
1624                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1625                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1626                     }
1627         }
1628         break;
1629         
1630     case AOP_STR:
1631         aop->coff = offset;
1632         if (strcmp(aop->aopu.aop_str[offset],s))
1633             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1634         break;
1635         
1636     case AOP_ACC:
1637         aop->coff = offset;
1638         if (!offset && (strcmp(s,"acc") == 0))
1639             break;
1640         
1641         if (strcmp(aop->aopu.aop_str[offset],s))
1642             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1643         break;
1644
1645     default :
1646         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1647                "pic16_aopPut got unsupported aop->type");
1648         exit(0);    
1649     }    
1650
1651 }
1652
1653 /*-----------------------------------------------------------------*/
1654 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1655 /*-----------------------------------------------------------------*/
1656 static void mov2w (asmop *aop, int offset)
1657 {
1658
1659   if(!aop)
1660     return;
1661
1662   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1663
1664   if ( aop->type == AOP_PCODE ||
1665        aop->type == AOP_LIT )
1666     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1667   else
1668     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1669
1670 }
1671
1672 /*-----------------------------------------------------------------*/
1673 /* reAdjustPreg - points a register back to where it should        */
1674 /*-----------------------------------------------------------------*/
1675 static void reAdjustPreg (asmop *aop)
1676 {
1677     int size ;
1678
1679     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1680     aop->coff = 0;
1681     if ((size = aop->size) <= 1)
1682         return ;
1683     size-- ;
1684     switch (aop->type) {
1685         case AOP_R0 :
1686         case AOP_R1 :
1687             while (size--)
1688                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1689             break;          
1690         case AOP_DPTR :
1691         case AOP_DPTR2:
1692             if (aop->type == AOP_DPTR2)
1693             {
1694                 genSetDPTR(1);
1695             } 
1696             while (size--)
1697             {
1698                 pic16_emitcode("lcall","__decdptr");
1699             }
1700                 
1701             if (aop->type == AOP_DPTR2)
1702             {
1703                 genSetDPTR(0);
1704             }                
1705             break;  
1706
1707     }   
1708
1709 }
1710
1711 /*-----------------------------------------------------------------*/
1712 /* genNotFloat - generates not for float operations              */
1713 /*-----------------------------------------------------------------*/
1714 static void genNotFloat (operand *op, operand *res)
1715 {
1716     int size, offset;
1717     char *l;
1718     symbol *tlbl ;
1719
1720     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1721     /* we will put 127 in the first byte of 
1722     the result */
1723     pic16_aopPut(AOP(res),"#127",0);
1724     size = AOP_SIZE(op) - 1;
1725     offset = 1;
1726
1727     l = pic16_aopGet(op->aop,offset++,FALSE,FALSE);
1728     MOVA(l);    
1729
1730     while(size--) {
1731         pic16_emitcode("orl","a,%s",
1732                  pic16_aopGet(op->aop,
1733                         offset++,FALSE,FALSE));
1734     }
1735     tlbl = newiTempLabel(NULL);
1736
1737     tlbl = newiTempLabel(NULL);
1738     pic16_aopPut(res->aop,one,1);
1739     pic16_emitcode("jz","%05d_DS_",(tlbl->key+100));
1740     pic16_aopPut(res->aop,zero,1);
1741     pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
1742
1743     size = res->aop->size - 2;
1744     offset = 2;    
1745     /* put zeros in the rest */
1746     while (size--) 
1747         pic16_aopPut(res->aop,zero,offset++);
1748 }
1749
1750 #if 0
1751 /*-----------------------------------------------------------------*/
1752 /* opIsGptr: returns non-zero if the passed operand is             */   
1753 /* a generic pointer type.                                         */
1754 /*-----------------------------------------------------------------*/ 
1755 static int opIsGptr(operand *op)
1756 {
1757     sym_link *type = operandType(op);
1758     
1759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1760     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1761     {
1762         return 1;
1763     }
1764     return 0;        
1765 }
1766 #endif
1767
1768 /*-----------------------------------------------------------------*/
1769 /* pic16_getDataSize - get the operand data size                         */
1770 /*-----------------------------------------------------------------*/
1771 int pic16_getDataSize(operand *op)
1772 {
1773     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1774
1775
1776     return AOP_SIZE(op);
1777
1778     // tsd- in the pic port, the genptr size is 1, so this code here
1779     // fails. ( in the 8051 port, the size was 4).
1780 #if 0
1781     int size;
1782     size = AOP_SIZE(op);
1783     if (size == GPTRSIZE)
1784     {
1785         sym_link *type = operandType(op);
1786         if (IS_GENPTR(type))
1787         {
1788             /* generic pointer; arithmetic operations
1789              * should ignore the high byte (pointer type).
1790              */
1791             size--;
1792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1793         }
1794     }
1795     return size;
1796 #endif
1797 }
1798
1799 /*-----------------------------------------------------------------*/
1800 /* pic16_outAcc - output Acc                                             */
1801 /*-----------------------------------------------------------------*/
1802 void pic16_outAcc(operand *result)
1803 {
1804   int size,offset;
1805   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1806   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1807
1808
1809   size = pic16_getDataSize(result);
1810   if(size){
1811     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1812     size--;
1813     offset = 1;
1814     /* unsigned or positive */
1815     while(size--)
1816       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1817   }
1818
1819 }
1820
1821 /*-----------------------------------------------------------------*/
1822 /* pic16_outBitC - output a bit C                                        */
1823 /*-----------------------------------------------------------------*/
1824 void pic16_outBitC(operand *result)
1825 {
1826
1827     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1828     /* if the result is bit */
1829     if (AOP_TYPE(result) == AOP_CRY) 
1830         pic16_aopPut(AOP(result),"c",0);
1831     else {
1832         pic16_emitcode("clr","a  ; %d", __LINE__);
1833         pic16_emitcode("rlc","a");
1834         pic16_outAcc(result);
1835     }
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1840 /*-----------------------------------------------------------------*/
1841 void pic16_toBoolean(operand *oper)
1842 {
1843     int size = AOP_SIZE(oper) - 1;
1844     int offset = 1;
1845
1846     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1847
1848     if ( AOP_TYPE(oper) != AOP_ACC) {
1849       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1850     }
1851     while (size--) {
1852       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1853     }
1854 }
1855
1856
1857 /*-----------------------------------------------------------------*/
1858 /* genNot - generate code for ! operation                          */
1859 /*-----------------------------------------------------------------*/
1860 static void genNot (iCode *ic)
1861 {
1862   symbol *tlbl;
1863   sym_link *optype = operandType(IC_LEFT(ic));
1864   int size;
1865
1866   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1867   /* assign asmOps to operand & result */
1868   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1869   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1870
1871   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1872   /* if in bit space then a special case */
1873   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1874     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1875       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1876       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1877     } else {
1878       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1879       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1880       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1881     }
1882     goto release;
1883   }
1884
1885   /* if type float then do float */
1886   if (IS_FLOAT(optype)) {
1887     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1888     goto release;
1889   }
1890
1891   size = AOP_SIZE(IC_RESULT(ic));
1892   if(size == 1) {
1893     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1894     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1895     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1896     goto release;
1897   }
1898   pic16_toBoolean(IC_LEFT(ic));
1899
1900   tlbl = newiTempLabel(NULL);
1901   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1902   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1903   pic16_outBitC(IC_RESULT(ic));
1904
1905  release:    
1906   /* release the aops */
1907   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1908   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* genCpl - generate code for complement                           */
1914 /*-----------------------------------------------------------------*/
1915 static void genCpl (iCode *ic)
1916 {
1917     int offset = 0;
1918     int size ;
1919
1920
1921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922     /* assign asmOps to operand & result */
1923     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1924     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1925
1926     /* if both are in bit space then 
1927     a special case */
1928     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1929         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1930
1931         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1932         pic16_emitcode("cpl","c"); 
1933         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1934         goto release; 
1935     } 
1936
1937     size = AOP_SIZE(IC_RESULT(ic));
1938     while (size--) {
1939         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1940         MOVA(l);       
1941         pic16_emitcode("cpl","a");
1942         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1943     }
1944
1945
1946 release:
1947     /* release the aops */
1948     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1949     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genUminusFloat - unary minus for floating points                */
1954 /*-----------------------------------------------------------------*/
1955 static void genUminusFloat(operand *op,operand *result)
1956 {
1957     int size ,offset =0 ;
1958     char *l;
1959
1960     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961     /* for this we just need to flip the 
1962     first it then copy the rest in place */
1963     size = AOP_SIZE(op) - 1;
1964     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
1965
1966     MOVA(l);    
1967
1968     pic16_emitcode("cpl","acc.7");
1969     pic16_aopPut(AOP(result),"a",3);    
1970
1971     while(size--) {
1972         pic16_aopPut(AOP(result),
1973                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
1974                offset);
1975         offset++;
1976     }          
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /* genUminus - unary minus code generation                         */
1981 /*-----------------------------------------------------------------*/
1982 static void genUminus (iCode *ic)
1983 {
1984   int size, i;
1985   sym_link *optype, *rtype;
1986
1987
1988   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1989   /* assign asmops */
1990   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
1991   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
1992
1993   /* if both in bit space then special
1994      case */
1995   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1996       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1997
1998     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1999     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2000     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2001
2002     goto release; 
2003   } 
2004
2005   optype = operandType(IC_LEFT(ic));
2006   rtype = operandType(IC_RESULT(ic));
2007
2008   /* if float then do float stuff */
2009   if (IS_FLOAT(optype)) {
2010     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2011     goto release;
2012   }
2013
2014   /* otherwise subtract from zero by taking the 2's complement */
2015   size = AOP_SIZE(IC_LEFT(ic));
2016
2017   for(i=0; i<size; i++) {
2018     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2019       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2020     else {
2021       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2023     }
2024   }
2025
2026   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2027   for(i=1; i<size; i++) {
2028     emitSKPNZ;
2029     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2030   }
2031
2032  release:
2033   /* release the aops */
2034   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2035   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2036 }
2037
2038 /*-----------------------------------------------------------------*/
2039 /* saveRegisters - will look for a call and save the registers     */
2040 /*-----------------------------------------------------------------*/
2041 static void saveRegisters(iCode *lic) 
2042 {
2043     int i;
2044     iCode *ic;
2045     bitVect *rsave;
2046     sym_link *dtype;
2047
2048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2049     /* look for call */
2050     for (ic = lic ; ic ; ic = ic->next) 
2051         if (ic->op == CALL || ic->op == PCALL)
2052             break;
2053
2054     if (!ic) {
2055         fprintf(stderr,"found parameter push with no function call\n");
2056         return ;
2057     }
2058
2059     /* if the registers have been saved already then
2060     do nothing */
2061     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2062         return ;
2063
2064     /* find the registers in use at this time 
2065     and push them away to safety */
2066     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2067                           ic->rUsed);
2068
2069     ic->regsSaved = 1;
2070     if (options.useXstack) {
2071         if (bitVectBitValue(rsave,R0_IDX))
2072             pic16_emitcode("mov","b,r0");
2073         pic16_emitcode("mov","r0,%s",spname);
2074         for (i = 0 ; i < pic16_nRegs ; i++) {
2075             if (bitVectBitValue(rsave,i)) {
2076                 if (i == R0_IDX)
2077                     pic16_emitcode("mov","a,b");
2078                 else
2079                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2080                 pic16_emitcode("movx","@r0,a");
2081                 pic16_emitcode("inc","r0");
2082             }
2083         }
2084         pic16_emitcode("mov","%s,r0",spname);
2085         if (bitVectBitValue(rsave,R0_IDX))
2086             pic16_emitcode("mov","r0,b");           
2087     }// else
2088     //for (i = 0 ; i < pic16_nRegs ; i++) {
2089     //    if (bitVectBitValue(rsave,i))
2090     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2091     //}
2092
2093     dtype = operandType(IC_LEFT(ic));
2094     if (currFunc && dtype && 
2095         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2096         IFFUNC_ISISR(currFunc->type) &&
2097         !ic->bankSaved) 
2098
2099         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2100
2101 }
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers                      */
2104 /*-----------------------------------------------------------------*/
2105 static void unsaveRegisters (iCode *ic)
2106 {
2107     int i;
2108     bitVect *rsave;
2109
2110     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2111     /* find the registers in use at this time 
2112     and push them away to safety */
2113     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2114                           ic->rUsed);
2115     
2116     if (options.useXstack) {
2117         pic16_emitcode("mov","r0,%s",spname);   
2118         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2119             if (bitVectBitValue(rsave,i)) {
2120                 pic16_emitcode("dec","r0");
2121                 pic16_emitcode("movx","a,@r0");
2122                 if (i == R0_IDX)
2123                     pic16_emitcode("mov","b,a");
2124                 else
2125                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2126             }       
2127
2128         }
2129         pic16_emitcode("mov","%s,r0",spname);
2130         if (bitVectBitValue(rsave,R0_IDX))
2131             pic16_emitcode("mov","r0,b");
2132     } //else
2133     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2134     //    if (bitVectBitValue(rsave,i))
2135     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2136     //}
2137
2138 }  
2139
2140
2141 /*-----------------------------------------------------------------*/
2142 /* pushSide -                                                      */
2143 /*-----------------------------------------------------------------*/
2144 static void pushSide(operand * oper, int size)
2145 {
2146 #if 0
2147         int offset = 0;
2148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2149         while (size--) {
2150                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2151                 if (AOP_TYPE(oper) != AOP_REG &&
2152                     AOP_TYPE(oper) != AOP_DIR &&
2153                     strcmp(l,"a") ) {
2154                         pic16_emitcode("mov","a,%s",l);
2155                         pic16_emitcode("push","acc");
2156                 } else
2157                         pic16_emitcode("push","%s",l);
2158         }
2159 #endif
2160 }
2161
2162 /*-----------------------------------------------------------------*/
2163 /* assignResultValue -                                             */
2164 /*-----------------------------------------------------------------*/
2165 static void assignResultValue(operand * oper)
2166 {
2167   int size = AOP_SIZE(oper);
2168
2169   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170
2171   DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2172
2173   if(!GpsuedoStkPtr) {
2174     /* The last byte in the assignment is in W */
2175     size--;
2176     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2177     GpsuedoStkPtr++;
2178   }
2179
2180   while (size--) {
2181     pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2182     GpsuedoStkPtr++;
2183     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2184   }
2185 }
2186
2187
2188 /*-----------------------------------------------------------------*/
2189 /* genIpush - genrate code for pushing this gets a little complex  */
2190 /*-----------------------------------------------------------------*/
2191 static void genIpush (iCode *ic)
2192 {
2193
2194   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2195 #if 0
2196     int size, offset = 0 ;
2197     char *l;
2198
2199
2200     /* if this is not a parm push : ie. it is spill push 
2201     and spill push is always done on the local stack */
2202     if (!ic->parmPush) {
2203
2204         /* and the item is spilt then do nothing */
2205         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2206             return ;
2207
2208         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2209         size = AOP_SIZE(IC_LEFT(ic));
2210         /* push it on the stack */
2211         while(size--) {
2212             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2213             if (*l == '#') {
2214                 MOVA(l);
2215                 l = "acc";
2216             }
2217             pic16_emitcode("push","%s",l);
2218         }
2219         return ;        
2220     }
2221
2222     /* this is a paramter push: in this case we call
2223     the routine to find the call and save those
2224     registers that need to be saved */   
2225     saveRegisters(ic);
2226
2227     /* then do the push */
2228     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2229
2230
2231         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2232     size = AOP_SIZE(IC_LEFT(ic));
2233
2234     while (size--) {
2235         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2236         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2237             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2238             strcmp(l,"a") ) {
2239             pic16_emitcode("mov","a,%s",l);
2240             pic16_emitcode("push","acc");
2241         } else
2242             pic16_emitcode("push","%s",l);
2243     }       
2244
2245     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2246 #endif
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* genIpop - recover the registers: can happen only for spilling   */
2251 /*-----------------------------------------------------------------*/
2252 static void genIpop (iCode *ic)
2253 {
2254   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2255 #if 0
2256     int size,offset ;
2257
2258
2259     /* if the temp was not pushed then */
2260     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2261         return ;
2262
2263     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2264     size = AOP_SIZE(IC_LEFT(ic));
2265     offset = (size-1);
2266     while (size--) 
2267         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2268                                    FALSE,TRUE));
2269
2270     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2271 #endif
2272 }
2273
2274 /*-----------------------------------------------------------------*/
2275 /* unsaverbank - restores the resgister bank from stack            */
2276 /*-----------------------------------------------------------------*/
2277 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2278 {
2279   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2280 #if 0
2281     int i;
2282     asmop *aop ;
2283     regs *r = NULL;
2284
2285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2286     if (popPsw) {
2287         if (options.useXstack) {
2288             aop = newAsmop(0);
2289             r = getFreePtr(ic,&aop,FALSE);
2290             
2291             
2292             pic16_emitcode("mov","%s,_spx",r->name);
2293             pic16_emitcode("movx","a,@%s",r->name);
2294             pic16_emitcode("mov","psw,a");
2295             pic16_emitcode("dec","%s",r->name);
2296             
2297         }else
2298             pic16_emitcode ("pop","psw");
2299     }
2300
2301     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2302         if (options.useXstack) {       
2303             pic16_emitcode("movx","a,@%s",r->name);
2304             //pic16_emitcode("mov","(%s+%d),a",
2305             //       regspic16[i].base,8*bank+regspic16[i].offset);
2306             pic16_emitcode("dec","%s",r->name);
2307
2308         } else 
2309           pic16_emitcode("pop",""); //"(%s+%d)",
2310         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2311     }
2312
2313     if (options.useXstack) {
2314
2315         pic16_emitcode("mov","_spx,%s",r->name);
2316         pic16_freeAsmop(NULL,aop,ic,TRUE);
2317
2318     }
2319 #endif 
2320 }
2321
2322 /*-----------------------------------------------------------------*/
2323 /* saverbank - saves an entire register bank on the stack          */
2324 /*-----------------------------------------------------------------*/
2325 static void saverbank (int bank, iCode *ic, bool pushPsw)
2326 {
2327   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2328 #if 0
2329     int i;
2330     asmop *aop ;
2331     regs *r = NULL;
2332
2333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334     if (options.useXstack) {
2335
2336         aop = newAsmop(0);
2337         r = getFreePtr(ic,&aop,FALSE);  
2338         pic16_emitcode("mov","%s,_spx",r->name);
2339
2340     }
2341
2342     for (i = 0 ; i < pic16_nRegs ;i++) {
2343         if (options.useXstack) {
2344             pic16_emitcode("inc","%s",r->name);
2345             //pic16_emitcode("mov","a,(%s+%d)",
2346             //         regspic16[i].base,8*bank+regspic16[i].offset);
2347             pic16_emitcode("movx","@%s,a",r->name);           
2348         } else 
2349           pic16_emitcode("push","");// "(%s+%d)",
2350                      //regspic16[i].base,8*bank+regspic16[i].offset);
2351     }
2352     
2353     if (pushPsw) {
2354         if (options.useXstack) {
2355             pic16_emitcode("mov","a,psw");
2356             pic16_emitcode("movx","@%s,a",r->name);     
2357             pic16_emitcode("inc","%s",r->name);
2358             pic16_emitcode("mov","_spx,%s",r->name);       
2359             pic16_freeAsmop (NULL,aop,ic,TRUE);
2360             
2361         } else
2362             pic16_emitcode("push","psw");
2363         
2364         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2365     }
2366     ic->bankSaved = 1;
2367 #endif
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* genCall - generates a call statement                            */
2372 /*-----------------------------------------------------------------*/
2373 static void genCall (iCode *ic)
2374 {
2375   sym_link *dtype;   
2376
2377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378
2379   /* if caller saves & we have not saved then */
2380   if (!ic->regsSaved)
2381     saveRegisters(ic);
2382
2383   /* if we are calling a function that is not using
2384      the same register bank then we need to save the
2385      destination registers on the stack */
2386   dtype = operandType(IC_LEFT(ic));
2387   if (currFunc && dtype && 
2388       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2389       IFFUNC_ISISR(currFunc->type) &&
2390       !ic->bankSaved) 
2391
2392     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2393
2394   /* if send set is not empty the assign */
2395   if (_G.sendSet) {
2396     iCode *sic;
2397     /* For the Pic port, there is no data stack.
2398      * So parameters passed to functions are stored
2399      * in registers. (The pCode optimizer will get
2400      * rid of most of these :).
2401      */
2402     int psuedoStkPtr=-1; 
2403     int firstTimeThruLoop = 1;
2404
2405     _G.sendSet = reverseSet(_G.sendSet);
2406
2407     /* First figure how many parameters are getting passed */
2408     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2409          sic = setNextItem(_G.sendSet)) {
2410
2411       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2412       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2413       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2414     }
2415
2416     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2417          sic = setNextItem(_G.sendSet)) {
2418       int size, offset = 0;
2419
2420       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2421       size = AOP_SIZE(IC_LEFT(sic));
2422
2423       while (size--) {
2424         DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2425                              pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2426
2427         if(!firstTimeThruLoop) {
2428           /* If this is not the first time we've been through the loop
2429            * then we need to save the parameter in a temporary
2430            * register. The last byte of the last parameter is
2431            * passed in W. */
2432           pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2433
2434         }
2435         firstTimeThruLoop=0;
2436
2437         //if (strcmp(l,fReturn[offset])) {
2438         mov2w (AOP(IC_LEFT(sic)),  offset);
2439 /*
2440         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2441              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2442           pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2443         else
2444           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2445 */
2446         //}
2447         offset++;
2448       }
2449       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2450     }
2451     _G.sendSet = NULL;
2452   }
2453   /* make the call */
2454   pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2455                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2456                                       OP_SYMBOL(IC_LEFT(ic))->name));
2457
2458   GpsuedoStkPtr=0;
2459   /* if we need assign a result value */
2460   if ((IS_ITEMP(IC_RESULT(ic)) && 
2461        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2462         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2463       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2464
2465     _G.accInUse++;
2466     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2467     _G.accInUse--;
2468
2469     assignResultValue(IC_RESULT(ic));
2470
2471     DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2472                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2473                 
2474     pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2475   }
2476
2477   /* adjust the stack for parameters if 
2478      required */
2479   if (ic->parmBytes) {
2480     int i;
2481     if (ic->parmBytes > 3) {
2482       pic16_emitcode("mov","a,%s",spname);
2483       pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2484       pic16_emitcode("mov","%s,a",spname);
2485     } else 
2486       for ( i = 0 ; i <  ic->parmBytes ;i++)
2487         pic16_emitcode("dec","%s",spname);
2488
2489   }
2490
2491   /* if register bank was saved then pop them */
2492   if (ic->bankSaved)
2493     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2494
2495   /* if we hade saved some registers then unsave them */
2496   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497     unsaveRegisters (ic);
2498
2499
2500 }
2501
2502 /*-----------------------------------------------------------------*/
2503 /* genPcall - generates a call by pointer statement                */
2504 /*-----------------------------------------------------------------*/
2505 static void genPcall (iCode *ic)
2506 {
2507     sym_link *dtype;
2508     symbol *rlbl = newiTempLabel(NULL);
2509
2510
2511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2512     /* if caller saves & we have not saved then */
2513     if (!ic->regsSaved)
2514         saveRegisters(ic);
2515
2516     /* if we are calling a function that is not using
2517     the same register bank then we need to save the
2518     destination registers on the stack */
2519     dtype = operandType(IC_LEFT(ic));
2520     if (currFunc && dtype && 
2521         IFFUNC_ISISR(currFunc->type) &&
2522         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2523         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2524
2525
2526     /* push the return address on to the stack */
2527     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2528     pic16_emitcode("push","acc");    
2529     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2530     pic16_emitcode("push","acc");
2531     
2532     if (options.model == MODEL_FLAT24)
2533     {
2534         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2535         pic16_emitcode("push","acc");    
2536     }
2537
2538     /* now push the calling address */
2539     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2540
2541     pushSide(IC_LEFT(ic), FPTRSIZE);
2542
2543     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2544
2545     /* if send set is not empty the assign */
2546     if (_G.sendSet) {
2547         iCode *sic ;
2548
2549         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2550              sic = setNextItem(_G.sendSet)) {
2551             int size, offset = 0;
2552             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2553             size = AOP_SIZE(IC_LEFT(sic));
2554             while (size--) {
2555                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2556                                 FALSE,FALSE);
2557                 if (strcmp(l,fReturn[offset]))
2558                     pic16_emitcode("mov","%s,%s",
2559                              fReturn[offset],
2560                              l);
2561                 offset++;
2562             }
2563             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2564         }
2565         _G.sendSet = NULL;
2566     }
2567
2568     pic16_emitcode("ret","");
2569     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2570
2571
2572     /* if we need assign a result value */
2573     if ((IS_ITEMP(IC_RESULT(ic)) &&
2574          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2575           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2576         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2577
2578         _G.accInUse++;
2579         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2580         _G.accInUse--;
2581         
2582         assignResultValue(IC_RESULT(ic));
2583
2584         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2585     }
2586
2587     /* adjust the stack for parameters if 
2588     required */
2589     if (ic->parmBytes) {
2590         int i;
2591         if (ic->parmBytes > 3) {
2592             pic16_emitcode("mov","a,%s",spname);
2593             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2594             pic16_emitcode("mov","%s,a",spname);
2595         } else 
2596             for ( i = 0 ; i <  ic->parmBytes ;i++)
2597                 pic16_emitcode("dec","%s",spname);
2598
2599     }
2600
2601     /* if register bank was saved then unsave them */
2602     if (currFunc && dtype && 
2603         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2604         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2605
2606     /* if we hade saved some registers then
2607     unsave them */
2608     if (ic->regsSaved)
2609         unsaveRegisters (ic);
2610
2611 }
2612
2613 /*-----------------------------------------------------------------*/
2614 /* resultRemat - result  is rematerializable                       */
2615 /*-----------------------------------------------------------------*/
2616 static int resultRemat (iCode *ic)
2617 {
2618   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2619   if (SKIP_IC(ic) || ic->op == IFX)
2620     return 0;
2621
2622   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2623     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2624     if (sym->remat && !POINTER_SET(ic)) 
2625       return 1;
2626   }
2627
2628   return 0;
2629 }
2630
2631 #if defined(__BORLANDC__) || defined(_MSC_VER)
2632 #define STRCASECMP stricmp
2633 #else
2634 #define STRCASECMP strcasecmp
2635 #endif
2636
2637 #if 0
2638 /*-----------------------------------------------------------------*/
2639 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2640 /*-----------------------------------------------------------------*/
2641 static bool inExcludeList(char *s)
2642 {
2643   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2644     int i =0;
2645     
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647     if (options.excludeRegs[i] &&
2648     STRCASECMP(options.excludeRegs[i],"none") == 0)
2649         return FALSE ;
2650
2651     for ( i = 0 ; options.excludeRegs[i]; i++) {
2652         if (options.excludeRegs[i] &&
2653         STRCASECMP(s,options.excludeRegs[i]) == 0)
2654             return TRUE;
2655     }
2656     return FALSE ;
2657 }
2658 #endif
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genFunction - generated code for function entry                 */
2662 /*-----------------------------------------------------------------*/
2663 static void genFunction (iCode *ic)
2664 {
2665     symbol *sym;
2666     sym_link *ftype;
2667
2668     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2669
2670     labelOffset += (max_key+4);
2671     max_key=0;
2672     GpsuedoStkPtr=0;
2673     _G.nRegsSaved = 0;
2674     /* create the function header */
2675     pic16_emitcode(";","-----------------------------------------");
2676     pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2677     pic16_emitcode(";","-----------------------------------------");
2678
2679     pic16_emitcode("","%s:",sym->rname);
2680     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
2681
2682     ftype = operandType(IC_LEFT(ic));
2683
2684     /* if critical function then turn interrupts off */
2685     if (IFFUNC_ISCRITICAL(ftype))
2686         pic16_emitcode("clr","ea");
2687
2688     /* here we need to generate the equates for the
2689        register bank if required */
2690 #if 0
2691     if (FUNC_REGBANK(ftype) != rbank) {
2692         int i ;
2693
2694         rbank = FUNC_REGBANK(ftype);
2695         for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2696             if (strcmp(regspic16[i].base,"0") == 0)
2697                 pic16_emitcode("","%s = 0x%02x",
2698                          regspic16[i].dname,
2699                          8*rbank+regspic16[i].offset);
2700             else
2701                 pic16_emitcode ("","%s = %s + 0x%02x",
2702                           regspic16[i].dname,
2703                           regspic16[i].base,
2704                           8*rbank+regspic16[i].offset);
2705         }
2706     }
2707 #endif
2708
2709     /* if this is an interrupt service routine then
2710     save acc, b, dpl, dph  */
2711     if (IFFUNC_ISISR(sym->type)) {
2712       pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
2713       pic16_emitpcodeNULLop(POC_NOP);
2714       pic16_emitpcodeNULLop(POC_NOP);
2715       pic16_emitpcodeNULLop(POC_NOP);
2716       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2717       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2718       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2719       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2720
2721       pic16_pBlockConvert2ISR(pb);
2722 #if 0  
2723         if (!inExcludeList("acc"))          
2724             pic16_emitcode ("push","acc");      
2725         if (!inExcludeList("b"))
2726             pic16_emitcode ("push","b");
2727         if (!inExcludeList("dpl"))
2728             pic16_emitcode ("push","dpl");
2729         if (!inExcludeList("dph"))
2730             pic16_emitcode ("push","dph");
2731         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2732         {
2733             pic16_emitcode ("push", "dpx");
2734             /* Make sure we're using standard DPTR */
2735             pic16_emitcode ("push", "dps");
2736             pic16_emitcode ("mov", "dps, #0x00");
2737             if (options.stack10bit)
2738             {   
2739                 /* This ISR could conceivably use DPTR2. Better save it. */
2740                 pic16_emitcode ("push", "dpl1");
2741                 pic16_emitcode ("push", "dph1");
2742                 pic16_emitcode ("push", "dpx1");
2743             }
2744         }
2745         /* if this isr has no bank i.e. is going to
2746            run with bank 0 , then we need to save more
2747            registers :-) */
2748         if (!FUNC_REGBANK(sym->type)) {
2749
2750             /* if this function does not call any other
2751                function then we can be economical and
2752                save only those registers that are used */
2753             if (! IFFUNC_HASFCALL(sym->type)) {
2754                 int i;
2755
2756                 /* if any registers used */
2757                 if (sym->regsUsed) {
2758                     /* save the registers used */
2759                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2760                         if (bitVectBitValue(sym->regsUsed,i) ||
2761                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2762                           pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
2763                     }
2764                 }
2765                 
2766             } else {
2767                 /* this function has  a function call cannot
2768                    determines register usage so we will have the
2769                    entire bank */
2770                 saverbank(0,ic,FALSE);
2771             }       
2772         }
2773 #endif
2774     } else {
2775         /* if callee-save to be used for this function
2776            then save the registers being used in this function */
2777         if (IFFUNC_CALLEESAVES(sym->type)) {
2778             int i;
2779             
2780             /* if any registers used */
2781             if (sym->regsUsed) {
2782                 /* save the registers used */
2783                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2784                     if (bitVectBitValue(sym->regsUsed,i) ||
2785                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2786                       //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2787                         _G.nRegsSaved++;
2788                     }
2789                 }
2790             }
2791         }
2792     }
2793
2794     /* set the register bank to the desired value */
2795     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2796         pic16_emitcode("push","psw");
2797         pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2798     }
2799
2800     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2801
2802         if (options.useXstack) {
2803             pic16_emitcode("mov","r0,%s",spname);
2804             pic16_emitcode("mov","a,_bp");
2805             pic16_emitcode("movx","@r0,a");
2806             pic16_emitcode("inc","%s",spname);
2807         }
2808         else
2809         {
2810             /* set up the stack */
2811             pic16_emitcode ("push","_bp");     /* save the callers stack  */
2812         }
2813         pic16_emitcode ("mov","_bp,%s",spname);
2814     }
2815
2816     /* adjust the stack for the function */
2817     if (sym->stack) {
2818
2819         int i = sym->stack;
2820         if (i > 256 ) 
2821             werror(W_STACK_OVERFLOW,sym->name);
2822
2823         if (i > 3 && sym->recvSize < 4) {              
2824
2825             pic16_emitcode ("mov","a,sp");
2826             pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2827             pic16_emitcode ("mov","sp,a");
2828            
2829         }
2830         else
2831             while(i--)
2832                 pic16_emitcode("inc","sp");
2833     }
2834
2835      if (sym->xstack) {
2836
2837         pic16_emitcode ("mov","a,_spx");
2838         pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2839         pic16_emitcode ("mov","_spx,a");
2840     }    
2841
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* genEndFunction - generates epilogue for functions               */
2846 /*-----------------------------------------------------------------*/
2847 static void genEndFunction (iCode *ic)
2848 {
2849     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2850
2851     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2852
2853     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2854     {
2855         pic16_emitcode ("mov","%s,_bp",spname);
2856     }
2857
2858     /* if use external stack but some variables were
2859     added to the local stack then decrement the
2860     local stack */
2861     if (options.useXstack && sym->stack) {      
2862         pic16_emitcode("mov","a,sp");
2863         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2864         pic16_emitcode("mov","sp,a");
2865     }
2866
2867
2868     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2869         if (options.useXstack) {
2870             pic16_emitcode("mov","r0,%s",spname);
2871             pic16_emitcode("movx","a,@r0");
2872             pic16_emitcode("mov","_bp,a");
2873             pic16_emitcode("dec","%s",spname);
2874         }
2875         else
2876         {
2877             pic16_emitcode ("pop","_bp");
2878         }
2879     }
2880
2881     /* restore the register bank  */    
2882     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2883         pic16_emitcode ("pop","psw");
2884
2885     if (IFFUNC_ISISR(sym->type)) {
2886
2887         /* now we need to restore the registers */
2888         /* if this isr has no bank i.e. is going to
2889            run with bank 0 , then we need to save more
2890            registers :-) */
2891         if (!FUNC_REGBANK(sym->type)) {
2892             
2893             /* if this function does not call any other
2894                function then we can be economical and
2895                save only those registers that are used */
2896             if (! IFFUNC_HASFCALL(sym->type)) {
2897                 int i;
2898                 
2899                 /* if any registers used */
2900                 if (sym->regsUsed) {
2901                     /* save the registers used */
2902                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2903                         if (bitVectBitValue(sym->regsUsed,i) ||
2904                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2905                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2906                     }
2907                 }
2908                 
2909             } else {
2910                 /* this function has  a function call cannot
2911                    determines register usage so we will have the
2912                    entire bank */
2913                 unsaverbank(0,ic,FALSE);
2914             }       
2915         }
2916 #if 0
2917         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2918         {
2919             if (options.stack10bit)
2920             {
2921                 pic16_emitcode ("pop", "dpx1");
2922                 pic16_emitcode ("pop", "dph1");
2923                 pic16_emitcode ("pop", "dpl1");
2924             }   
2925             pic16_emitcode ("pop", "dps");
2926             pic16_emitcode ("pop", "dpx");
2927         }
2928         if (!inExcludeList("dph"))
2929             pic16_emitcode ("pop","dph");
2930         if (!inExcludeList("dpl"))
2931             pic16_emitcode ("pop","dpl");
2932         if (!inExcludeList("b"))
2933             pic16_emitcode ("pop","b");
2934         if (!inExcludeList("acc"))
2935             pic16_emitcode ("pop","acc");
2936
2937         if (IFFUNC_ISCRITICAL(sym->type))
2938             pic16_emitcode("setb","ea");
2939 #endif
2940
2941         /* if debug then send end of function */
2942 /*      if (options.debug && currFunc) { */
2943         if (currFunc) {
2944             _G.debugLine = 1;
2945             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2946                      FileBaseName(ic->filename),currFunc->lastLine,
2947                      ic->level,ic->block); 
2948             if (IS_STATIC(currFunc->etype))         
2949                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2950             else
2951                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2952             _G.debugLine = 0;
2953         }
2954         
2955         pic16_emitcode ("reti","");
2956
2957         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2958         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
2959         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
2960         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
2961         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
2962         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
2963
2964         pic16_emitpcodeNULLop(POC_RETFIE);
2965
2966     }
2967     else {
2968         if (IFFUNC_ISCRITICAL(sym->type))
2969             pic16_emitcode("setb","ea");
2970         
2971         if (IFFUNC_CALLEESAVES(sym->type)) {
2972             int i;
2973             
2974             /* if any registers used */
2975             if (sym->regsUsed) {
2976                 /* save the registers used */
2977                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2978                     if (bitVectBitValue(sym->regsUsed,i) ||
2979                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2980                       pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2981                 }
2982             }
2983             
2984         }
2985
2986         /* if debug then send end of function */
2987         if (currFunc) {
2988             _G.debugLine = 1;
2989             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2990                      FileBaseName(ic->filename),currFunc->lastLine,
2991                      ic->level,ic->block); 
2992             if (IS_STATIC(currFunc->etype))         
2993                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2994             else
2995                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2996             _G.debugLine = 0;
2997         }
2998
2999         pic16_emitcode ("return","");
3000         pic16_emitpcodeNULLop(POC_RETURN);
3001
3002         /* Mark the end of a function */
3003         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3004     }
3005
3006 }
3007
3008 /*-----------------------------------------------------------------*/
3009 /* genRet - generate code for return statement                     */
3010 /*-----------------------------------------------------------------*/
3011 static void genRet (iCode *ic)
3012 {
3013   int size,offset = 0 , pushed = 0;
3014     
3015   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3016   /* if we have no return value then
3017      just generate the "ret" */
3018   if (!IC_LEFT(ic)) 
3019     goto jumpret;       
3020     
3021   /* we have something to return then
3022      move the return value into place */
3023   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3024   size = AOP_SIZE(IC_LEFT(ic));
3025     
3026   while (size--) {
3027     char *l ;
3028     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3029       /* #NOCHANGE */
3030       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3031                  FALSE,TRUE);
3032       pic16_emitcode("push","%s",l);
3033       pushed++;
3034     } else {
3035       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3036                  FALSE,FALSE);
3037       if (strcmp(fReturn[offset],l)) {
3038         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3039             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3040           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3041         }else {
3042           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3043         }
3044         if(size) {
3045           pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
3046         }
3047         offset++;
3048       }
3049     }
3050   }    
3051
3052   if (pushed) {
3053     while(pushed) {
3054       pushed--;
3055       if (strcmp(fReturn[pushed],"a"))
3056         pic16_emitcode("pop",fReturn[pushed]);
3057       else
3058         pic16_emitcode("pop","acc");
3059     }
3060   }
3061   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3062     
3063  jumpret:
3064   /* generate a jump to the return label
3065      if the next is not the return statement */
3066   if (!(ic->next && ic->next->op == LABEL &&
3067         IC_LABEL(ic->next) == returnLabel)) {
3068         
3069     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3070     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3071   }
3072     
3073 }
3074
3075 /*-----------------------------------------------------------------*/
3076 /* genLabel - generates a label                                    */
3077 /*-----------------------------------------------------------------*/
3078 static void genLabel (iCode *ic)
3079 {
3080     /* special case never generate */
3081     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3082     if (IC_LABEL(ic) == entryLabel)
3083         return ;
3084
3085     pic16_emitpLabel(IC_LABEL(ic)->key);
3086     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3087 }
3088
3089 /*-----------------------------------------------------------------*/
3090 /* genGoto - generates a goto                                      */
3091 /*-----------------------------------------------------------------*/
3092 //tsd
3093 static void genGoto (iCode *ic)
3094 {
3095   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3096   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3097 }
3098
3099
3100 /*-----------------------------------------------------------------*/
3101 /* genMultbits :- multiplication of bits                           */
3102 /*-----------------------------------------------------------------*/
3103 static void genMultbits (operand *left, 
3104                          operand *right, 
3105                          operand *result)
3106 {
3107   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3108
3109   if(!pic16_sameRegs(AOP(result),AOP(right)))
3110     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3111
3112   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3113   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3114   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3115
3116 }
3117
3118
3119 /*-----------------------------------------------------------------*/
3120 /* genMultOneByte : 8 bit multiplication & division                */
3121 /*-----------------------------------------------------------------*/
3122 static void genMultOneByte (operand *left,
3123                             operand *right,
3124                             operand *result)
3125 {
3126   sym_link *opetype = operandType(result);
3127
3128   // symbol *lbl ;
3129   int size,offset;
3130
3131   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3132   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3133   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3134
3135   /* (if two literals, the value is computed before) */
3136   /* if one literal, literal on the right */
3137   if (AOP_TYPE(left) == AOP_LIT){
3138     operand *t = right;
3139     right = left;
3140     left = t;
3141   }
3142
3143   size = AOP_SIZE(result);
3144   if(size == 1) {
3145
3146     if (AOP_TYPE(right) == AOP_LIT){
3147       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3148                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3149                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3150                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3151       pic16_emitcode("call","genMultLit");
3152     } else {
3153       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3154                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3155                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3156                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3157       pic16_emitcode("call","pic16_genMult8X8_8");
3158
3159     }
3160     pic16_genMult8X8_8 (left, right,result);
3161
3162
3163     /* signed or unsigned */
3164     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3165     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3166     //MOVA(l);       
3167     //pic16_emitcode("mul","ab");
3168     /* if result size = 1, mul signed = mul unsigned */
3169     //pic16_aopPut(AOP(result),"a",0);
3170
3171   } else {  // (size > 1)
3172
3173     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3174                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3175                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3176                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3177
3178     if (SPEC_USIGN(opetype)){
3179       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3180       pic16_genUMult8X8_16 (left, right, result, NULL);
3181
3182       if (size > 2) {
3183         /* for filling the MSBs */
3184         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3185         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3186       }
3187     }
3188     else{
3189       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3190
3191       pic16_emitcode("mov","a,b");
3192
3193       /* adjust the MSB if left or right neg */
3194
3195       /* if one literal */
3196       if (AOP_TYPE(right) == AOP_LIT){
3197         pic16_emitcode("multiply ","right is a lit");
3198         /* AND literal negative */
3199         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3200           /* adjust MSB (c==0 after mul) */
3201           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3202         }
3203       }
3204       else{
3205         pic16_genSMult8X8_16 (left, right, result, NULL);
3206       }
3207
3208       if(size > 2){
3209         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3210         /* get the sign */
3211         pic16_emitcode("rlc","a");
3212         pic16_emitcode("subb","a,acc");
3213       }
3214     }
3215
3216     size -= 2;   
3217     offset = 2;
3218     if (size > 0)
3219       while (size--)
3220         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3221     //pic16_aopPut(AOP(result),"a",offset++);
3222   }
3223 }
3224
3225 /*-----------------------------------------------------------------*/
3226 /* genMult - generates code for multiplication                     */
3227 /*-----------------------------------------------------------------*/
3228 static void genMult (iCode *ic)
3229 {
3230     operand *left = IC_LEFT(ic);
3231     operand *right = IC_RIGHT(ic);
3232     operand *result= IC_RESULT(ic);   
3233
3234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3235     /* assign the amsops */
3236     pic16_aopOp (left,ic,FALSE);
3237     pic16_aopOp (right,ic,FALSE);
3238     pic16_aopOp (result,ic,TRUE);
3239
3240   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3241
3242     /* special cases first */
3243     /* both are bits */
3244     if (AOP_TYPE(left) == AOP_CRY &&
3245         AOP_TYPE(right)== AOP_CRY) {
3246         genMultbits(left,right,result);
3247         goto release ;
3248     }
3249
3250     /* if both are of size == 1 */
3251     if (AOP_SIZE(left) == 1 &&
3252         AOP_SIZE(right) == 1 ) {
3253         genMultOneByte(left,right,result);
3254         goto release ;
3255     }
3256
3257     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3258
3259     /* should have been converted to function call */
3260     //assert(0) ;
3261
3262 release :
3263     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3264     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3265     pic16_freeAsmop(result,NULL,ic,TRUE); 
3266 }
3267
3268 /*-----------------------------------------------------------------*/
3269 /* genDivbits :- division of bits                                  */
3270 /*-----------------------------------------------------------------*/
3271 static void genDivbits (operand *left, 
3272                         operand *right, 
3273                         operand *result)
3274 {
3275
3276     char *l;
3277
3278     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3279     /* the result must be bit */    
3280     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3281     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3282
3283     MOVA(l);    
3284
3285     pic16_emitcode("div","ab");
3286     pic16_emitcode("rrc","a");
3287     pic16_aopPut(AOP(result),"c",0);
3288 }
3289
3290 /*-----------------------------------------------------------------*/
3291 /* genDivOneByte : 8 bit division                                  */
3292 /*-----------------------------------------------------------------*/
3293 static void genDivOneByte (operand *left,
3294                            operand *right,
3295                            operand *result)
3296 {
3297     sym_link *opetype = operandType(result);
3298     char *l ;
3299     symbol *lbl ;
3300     int size,offset;
3301
3302     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3303     size = AOP_SIZE(result) - 1;
3304     offset = 1;
3305     /* signed or unsigned */
3306     if (SPEC_USIGN(opetype)) {
3307         /* unsigned is easy */
3308         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3309         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3310         MOVA(l);        
3311         pic16_emitcode("div","ab");
3312         pic16_aopPut(AOP(result),"a",0);
3313         while (size--)
3314             pic16_aopPut(AOP(result),zero,offset++);
3315         return ;
3316     }
3317
3318     /* signed is a little bit more difficult */
3319
3320     /* save the signs of the operands */
3321     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3322     MOVA(l);    
3323     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3324     pic16_emitcode("push","acc"); /* save it on the stack */
3325
3326     /* now sign adjust for both left & right */
3327     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3328     MOVA(l);       
3329     lbl = newiTempLabel(NULL);
3330     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3331     pic16_emitcode("cpl","a");   
3332     pic16_emitcode("inc","a");
3333     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3334     pic16_emitcode("mov","b,a");
3335
3336     /* sign adjust left side */
3337     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3338     MOVA(l);
3339
3340     lbl = newiTempLabel(NULL);
3341     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3342     pic16_emitcode("cpl","a");
3343     pic16_emitcode("inc","a");
3344     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3345
3346     /* now the division */
3347     pic16_emitcode("div","ab");
3348     /* we are interested in the lower order
3349     only */
3350     pic16_emitcode("mov","b,a");
3351     lbl = newiTempLabel(NULL);
3352     pic16_emitcode("pop","acc");   
3353     /* if there was an over flow we don't 
3354     adjust the sign of the result */
3355     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3356     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3357     CLRC;
3358     pic16_emitcode("clr","a");
3359     pic16_emitcode("subb","a,b");
3360     pic16_emitcode("mov","b,a");
3361     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3362
3363     /* now we are done */
3364     pic16_aopPut(AOP(result),"b",0);
3365     if(size > 0){
3366         pic16_emitcode("mov","c,b.7");
3367         pic16_emitcode("subb","a,acc");   
3368     }
3369     while (size--)
3370         pic16_aopPut(AOP(result),"a",offset++);
3371
3372 }
3373
3374 /*-----------------------------------------------------------------*/
3375 /* genDiv - generates code for division                            */
3376 /*-----------------------------------------------------------------*/
3377 static void genDiv (iCode *ic)
3378 {
3379     operand *left = IC_LEFT(ic);
3380     operand *right = IC_RIGHT(ic);
3381     operand *result= IC_RESULT(ic);   
3382
3383     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3384     /* assign the amsops */
3385     pic16_aopOp (left,ic,FALSE);
3386     pic16_aopOp (right,ic,FALSE);
3387     pic16_aopOp (result,ic,TRUE);
3388
3389     /* special cases first */
3390     /* both are bits */
3391     if (AOP_TYPE(left) == AOP_CRY &&
3392         AOP_TYPE(right)== AOP_CRY) {
3393         genDivbits(left,right,result);
3394         goto release ;
3395     }
3396
3397     /* if both are of size == 1 */
3398     if (AOP_SIZE(left) == 1 &&
3399         AOP_SIZE(right) == 1 ) {
3400         genDivOneByte(left,right,result);
3401         goto release ;
3402     }
3403
3404     /* should have been converted to function call */
3405     assert(0);
3406 release :
3407     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3408     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3409     pic16_freeAsmop(result,NULL,ic,TRUE); 
3410 }
3411
3412 /*-----------------------------------------------------------------*/
3413 /* genModbits :- modulus of bits                                   */
3414 /*-----------------------------------------------------------------*/
3415 static void genModbits (operand *left, 
3416                         operand *right, 
3417                         operand *result)
3418 {
3419
3420     char *l;
3421
3422     /* the result must be bit */    
3423     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3424     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3425
3426     MOVA(l);       
3427
3428     pic16_emitcode("div","ab");
3429     pic16_emitcode("mov","a,b");
3430     pic16_emitcode("rrc","a");
3431     pic16_aopPut(AOP(result),"c",0);
3432 }
3433
3434 /*-----------------------------------------------------------------*/
3435 /* genModOneByte : 8 bit modulus                                   */
3436 /*-----------------------------------------------------------------*/
3437 static void genModOneByte (operand *left,
3438                            operand *right,
3439                            operand *result)
3440 {
3441     sym_link *opetype = operandType(result);
3442     char *l ;
3443     symbol *lbl ;
3444
3445     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3446     /* signed or unsigned */
3447     if (SPEC_USIGN(opetype)) {
3448         /* unsigned is easy */
3449         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3450         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3451         MOVA(l);    
3452         pic16_emitcode("div","ab");
3453         pic16_aopPut(AOP(result),"b",0);
3454         return ;
3455     }
3456
3457     /* signed is a little bit more difficult */
3458
3459     /* save the signs of the operands */
3460     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3461     MOVA(l);
3462
3463     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3464     pic16_emitcode("push","acc"); /* save it on the stack */
3465
3466     /* now sign adjust for both left & right */
3467     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3468     MOVA(l);
3469
3470     lbl = newiTempLabel(NULL);
3471     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3472     pic16_emitcode("cpl","a");   
3473     pic16_emitcode("inc","a");
3474     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3475     pic16_emitcode("mov","b,a"); 
3476
3477     /* sign adjust left side */
3478     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3479     MOVA(l);
3480
3481     lbl = newiTempLabel(NULL);
3482     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3483     pic16_emitcode("cpl","a");   
3484     pic16_emitcode("inc","a");
3485     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3486
3487     /* now the multiplication */
3488     pic16_emitcode("div","ab");
3489     /* we are interested in the lower order
3490     only */
3491     lbl = newiTempLabel(NULL);
3492     pic16_emitcode("pop","acc");   
3493     /* if there was an over flow we don't 
3494     adjust the sign of the result */
3495     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3496     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3497     CLRC ;
3498     pic16_emitcode("clr","a");
3499     pic16_emitcode("subb","a,b");
3500     pic16_emitcode("mov","b,a");
3501     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3502
3503     /* now we are done */
3504     pic16_aopPut(AOP(result),"b",0);
3505
3506 }
3507
3508 /*-----------------------------------------------------------------*/
3509 /* genMod - generates code for division                            */
3510 /*-----------------------------------------------------------------*/
3511 static void genMod (iCode *ic)
3512 {
3513     operand *left = IC_LEFT(ic);
3514     operand *right = IC_RIGHT(ic);
3515     operand *result= IC_RESULT(ic);  
3516
3517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3518     /* assign the amsops */
3519     pic16_aopOp (left,ic,FALSE);
3520     pic16_aopOp (right,ic,FALSE);
3521     pic16_aopOp (result,ic,TRUE);
3522
3523     /* special cases first */
3524     /* both are bits */
3525     if (AOP_TYPE(left) == AOP_CRY &&
3526         AOP_TYPE(right)== AOP_CRY) {
3527         genModbits(left,right,result);
3528         goto release ;
3529     }
3530
3531     /* if both are of size == 1 */
3532     if (AOP_SIZE(left) == 1 &&
3533         AOP_SIZE(right) == 1 ) {
3534         genModOneByte(left,right,result);
3535         goto release ;
3536     }
3537
3538     /* should have been converted to function call */
3539     assert(0);
3540
3541 release :
3542     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3543     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3544     pic16_freeAsmop(result,NULL,ic,TRUE); 
3545 }
3546
3547 /*-----------------------------------------------------------------*/
3548 /* genIfxJump :- will create a jump depending on the ifx           */
3549 /*-----------------------------------------------------------------*/
3550 /*
3551   note: May need to add parameter to indicate when a variable is in bit space.
3552 */
3553 static void genIfxJump (iCode *ic, char *jval)
3554 {
3555
3556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3557     /* if true label then we jump if condition
3558     supplied is true */
3559     if ( IC_TRUE(ic) ) {
3560
3561         if(strcmp(jval,"a") == 0)
3562           emitSKPZ;
3563         else if (strcmp(jval,"c") == 0)
3564           emitSKPC;
3565         else {
3566           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3567           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3568         }
3569
3570         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3571         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3572
3573     }
3574     else {
3575         /* false label is present */
3576         if(strcmp(jval,"a") == 0)
3577           emitSKPNZ;
3578         else if (strcmp(jval,"c") == 0)
3579           emitSKPNC;
3580         else {
3581           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3582           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3583         }
3584
3585         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3586         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3587
3588     }
3589
3590
3591     /* mark the icode as generated */
3592     ic->generated = 1;
3593 }
3594
3595 /*-----------------------------------------------------------------*/
3596 /* genSkip                                                         */
3597 /*-----------------------------------------------------------------*/
3598 static void genSkip(iCode *ifx,int status_bit)
3599 {
3600   if(!ifx)
3601     return;
3602
3603   if ( IC_TRUE(ifx) ) {
3604     switch(status_bit) {
3605     case 'z':
3606       emitSKPNZ;
3607       break;
3608
3609     case 'c':
3610       emitSKPNC;
3611       break;
3612
3613     case 'd':
3614       emitSKPDC;
3615       break;
3616
3617     }
3618
3619     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3620     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3621
3622   } else {
3623
3624     switch(status_bit) {
3625
3626     case 'z':
3627       emitSKPZ;
3628       break;
3629
3630     case 'c':
3631       emitSKPC;
3632       break;
3633
3634     case 'd':
3635       emitSKPDC;
3636       break;
3637     }
3638     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3639     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3640
3641   }
3642
3643 }
3644
3645 /*-----------------------------------------------------------------*/
3646 /* genSkipc                                                        */
3647 /*-----------------------------------------------------------------*/
3648 static void genSkipc(resolvedIfx *rifx)
3649 {
3650   if(!rifx)
3651     return;
3652
3653   if(rifx->condition)
3654     emitSKPC;
3655   else
3656     emitSKPNC;
3657
3658   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3659   rifx->generated = 1;
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /* genSkipz2                                                       */
3664 /*-----------------------------------------------------------------*/
3665 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3666 {
3667   if(!rifx)
3668     return;
3669
3670   if( (rifx->condition ^ invert_condition) & 1)
3671     emitSKPZ;
3672   else
3673     emitSKPNZ;
3674
3675   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3676   rifx->generated = 1;
3677 }
3678
3679 /*-----------------------------------------------------------------*/
3680 /* genSkipz                                                        */
3681 /*-----------------------------------------------------------------*/
3682 static void genSkipz(iCode *ifx, int condition)
3683 {
3684   if(!ifx)
3685     return;
3686
3687   if(condition)
3688     emitSKPNZ;
3689   else
3690     emitSKPZ;
3691
3692   if ( IC_TRUE(ifx) )
3693     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3694   else
3695     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3696
3697   if ( IC_TRUE(ifx) )
3698     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3699   else
3700     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3701
3702 }
3703 /*-----------------------------------------------------------------*/
3704 /* genSkipCond                                                     */
3705 /*-----------------------------------------------------------------*/
3706 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3707 {
3708   if(!rifx)
3709     return;
3710
3711   if(rifx->condition)
3712     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3713   else
3714     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3715
3716
3717   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3718   rifx->generated = 1;
3719 }
3720
3721 #if 0
3722 /*-----------------------------------------------------------------*/
3723 /* genChkZeroes :- greater or less than comparison                 */
3724 /*     For each byte in a literal that is zero, inclusive or the   */
3725 /*     the corresponding byte in the operand with W                */
3726 /*     returns true if any of the bytes are zero                   */
3727 /*-----------------------------------------------------------------*/
3728 static int genChkZeroes(operand *op, int lit,  int size)
3729 {
3730
3731   int i;
3732   int flag =1;
3733
3734   while(size--) {
3735     i = (lit >> (size*8)) & 0xff;
3736
3737     if(i==0) {
3738       if(flag) 
3739         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3740       else
3741         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3742       flag = 0;
3743     }
3744   }
3745
3746   return (flag==0);
3747 }
3748 #endif
3749
3750 /*-----------------------------------------------------------------*/
3751 /* genCmp :- greater or less than comparison                       */
3752 /*-----------------------------------------------------------------*/
3753 static void genCmp (operand *left,operand *right,
3754                     operand *result, iCode *ifx, int sign)
3755 {
3756   int size; //, offset = 0 ;
3757   unsigned long lit = 0L,i = 0;
3758   resolvedIfx rFalseIfx;
3759   //  resolvedIfx rTrueIfx;
3760   symbol *truelbl;
3761   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3762 /*
3763   if(ifx) {
3764     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3765     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3766   }
3767 */
3768
3769   resolveIfx(&rFalseIfx,ifx);
3770   truelbl  = newiTempLabel(NULL);
3771   size = max(AOP_SIZE(left),AOP_SIZE(right));
3772
3773   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3774
3775 #define _swapp
3776
3777   /* if literal is on the right then swap with left */
3778   if ((AOP_TYPE(right) == AOP_LIT)) {
3779     operand *tmp = right ;
3780     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3781     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3782 #ifdef _swapp
3783
3784     lit = (lit - 1) & mask;
3785     right = left;
3786     left = tmp;
3787     rFalseIfx.condition ^= 1;
3788 #endif
3789
3790   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3791     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3792   }
3793
3794
3795   //if(IC_TRUE(ifx) == NULL)
3796   /* if left & right are bit variables */
3797   if (AOP_TYPE(left) == AOP_CRY &&
3798       AOP_TYPE(right) == AOP_CRY ) {
3799     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3800     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3801   } else {
3802     /* subtract right from left if at the
3803        end the carry flag is set then we know that
3804        left is greater than right */
3805
3806     //    {
3807
3808     symbol *lbl  = newiTempLabel(NULL);
3809
3810 #ifndef _swapp
3811     if(AOP_TYPE(right) == AOP_LIT) {
3812
3813       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3814
3815       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3816
3817       /* special cases */
3818
3819       if(lit == 0) {
3820
3821         if(sign != 0) 
3822           genSkipCond(&rFalseIfx,left,size-1,7);
3823         else 
3824           /* no need to compare to 0...*/
3825           /* NOTE: this is a de-generate compare that most certainly 
3826            *       creates some dead code. */
3827           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
3828
3829         if(ifx) ifx->generated = 1;
3830         return;
3831
3832       }
3833       size--;
3834
3835       if(size == 0) {
3836         //i = (lit >> (size*8)) & 0xff;
3837         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3838         
3839         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3840
3841         i = ((0-lit) & 0xff);
3842         if(sign) {
3843           if( i == 0x81) { 
3844             /* lit is 0x7f, all signed chars are less than
3845              * this except for 0x7f itself */
3846             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
3847             genSkipz2(&rFalseIfx,0);
3848           } else {
3849             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
3850             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
3851             genSkipc(&rFalseIfx);
3852           }
3853
3854         } else {
3855           if(lit == 1) {
3856             genSkipz2(&rFalseIfx,1);
3857           } else {
3858             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
3859             genSkipc(&rFalseIfx);
3860           }
3861         }
3862
3863         if(ifx) ifx->generated = 1;
3864         return;
3865       }
3866
3867       /* chars are out of the way. now do ints and longs */
3868
3869
3870       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3871         
3872       /* special cases */
3873
3874       if(sign) {
3875
3876         if(lit == 0) {
3877           genSkipCond(&rFalseIfx,left,size,7);
3878           if(ifx) ifx->generated = 1;
3879           return;
3880         }
3881
3882         if(lit <0x100) {
3883           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3884
3885           //rFalseIfx.condition ^= 1;
3886           //genSkipCond(&rFalseIfx,left,size,7);
3887           //rFalseIfx.condition ^= 1;
3888
3889           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3890           if(rFalseIfx.condition)
3891             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3892           else
3893             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3894
3895           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
3896           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3897           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
3898
3899           while(size > 1)
3900             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
3901
3902           if(rFalseIfx.condition) {
3903             emitSKPZ;
3904             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3905
3906           } else {
3907             emitSKPNZ;
3908           }
3909
3910           genSkipc(&rFalseIfx);
3911           pic16_emitpLabel(truelbl->key);
3912           if(ifx) ifx->generated = 1;
3913           return;
3914
3915         }
3916
3917         if(size == 1) {
3918
3919           if( (lit & 0xff) == 0) {
3920             /* lower byte is zero */
3921             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3922             i = ((lit >> 8) & 0xff) ^0x80;
3923             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3924             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3925             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3926             genSkipc(&rFalseIfx);
3927
3928
3929             if(ifx) ifx->generated = 1;
3930             return;
3931
3932           }
3933         } else {
3934           /* Special cases for signed longs */
3935           if( (lit & 0xffffff) == 0) {
3936             /* lower byte is zero */
3937             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3938             i = ((lit >> 8*3) & 0xff) ^0x80;
3939             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3940             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3941             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3942             genSkipc(&rFalseIfx);
3943
3944
3945             if(ifx) ifx->generated = 1;
3946             return;
3947
3948           }
3949
3950         }
3951
3952
3953         if(lit & (0x80 << (size*8))) {
3954           /* lit is negative */
3955           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3956
3957           //genSkipCond(&rFalseIfx,left,size,7);
3958
3959           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3960
3961           if(rFalseIfx.condition)
3962             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3963           else
3964             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3965
3966
3967         } else {
3968           /* lit is positive */
3969           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3970           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3971           if(rFalseIfx.condition)
3972             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3973           else
3974             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3975
3976         }
3977
3978         /*
3979           This works, but is only good for ints.
3980           It also requires a "known zero" register.
3981           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
3982           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3983           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
3984           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
3985           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
3986           genSkipc(&rFalseIfx);
3987
3988           pic16_emitpLabel(truelbl->key);
3989           if(ifx) ifx->generated = 1;
3990           return;
3991         **/
3992           
3993         /* There are no more special cases, so perform a general compare */
3994   
3995         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
3996         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
3997
3998         while(size--) {
3999
4000           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4001           emitSKPNZ;
4002           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4003         }
4004         //rFalseIfx.condition ^= 1;
4005         genSkipc(&rFalseIfx);
4006
4007         pic16_emitpLabel(truelbl->key);
4008
4009         if(ifx) ifx->generated = 1;
4010         return;
4011
4012
4013       }
4014
4015
4016       /* sign is out of the way. So now do an unsigned compare */
4017       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4018
4019
4020       /* General case - compare to an unsigned literal on the right.*/
4021
4022       i = (lit >> (size*8)) & 0xff;
4023       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4024       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4025       while(size--) {
4026         i = (lit >> (size*8)) & 0xff;
4027
4028         if(i) {
4029           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4030           emitSKPNZ;
4031           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4032         } else {
4033           /* this byte of the lit is zero, 
4034            *if it's not the last then OR in the variable */
4035           if(size)
4036             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4037         }
4038       }
4039
4040
4041       pic16_emitpLabel(lbl->key);
4042       //if(emitFinalCheck)
4043       genSkipc(&rFalseIfx);
4044       if(sign)
4045         pic16_emitpLabel(truelbl->key);
4046
4047       if(ifx) ifx->generated = 1;
4048       return;
4049
4050
4051     }
4052 #endif  // _swapp
4053
4054     if(AOP_TYPE(left) == AOP_LIT) {
4055       //symbol *lbl = newiTempLabel(NULL);
4056
4057       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4058
4059
4060       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4061
4062       /* Special cases */
4063       if((lit == 0) && (sign == 0)){
4064
4065         size--;
4066         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4067         while(size) 
4068           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4069
4070         genSkipz2(&rFalseIfx,0);
4071         if(ifx) ifx->generated = 1;
4072         return;
4073       }
4074
4075       if(size==1) {
4076         /* Special cases */
4077         lit &= 0xff;
4078         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4079           /* degenerate compare can never be true */
4080           if(rFalseIfx.condition == 0)
4081             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4082
4083           if(ifx) ifx->generated = 1;
4084           return;
4085         }
4086
4087         if(sign) {
4088           /* signed comparisons to a literal byte */
4089
4090           int lp1 = (lit+1) & 0xff;
4091
4092           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4093           switch (lp1) {
4094           case 0:
4095             rFalseIfx.condition ^= 1;
4096             genSkipCond(&rFalseIfx,right,0,7);
4097             break;
4098           case 0x7f:
4099             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4100             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4101             genSkipz2(&rFalseIfx,1);
4102             break;
4103           default:
4104             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4105             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4106             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4107             rFalseIfx.condition ^= 1;
4108             genSkipc(&rFalseIfx);
4109             break;
4110           }
4111         } else {
4112           /* unsigned comparisons to a literal byte */
4113
4114           switch(lit & 0xff ) {
4115           case 0:
4116             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4117             genSkipz2(&rFalseIfx,0);
4118             break;
4119           case 0x7f:
4120             rFalseIfx.condition ^= 1;
4121             genSkipCond(&rFalseIfx,right,0,7);
4122             break;
4123
4124           default:
4125             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4126             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4127             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4128             rFalseIfx.condition ^= 1;
4129             if (AOP_TYPE(result) == AOP_CRY)
4130               genSkipc(&rFalseIfx);
4131             else {
4132               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4133               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4134             }         
4135             break;
4136           }
4137         }
4138
4139         if(ifx) ifx->generated = 1;
4140         //goto check_carry;
4141         return;
4142
4143       } else {
4144
4145         /* Size is greater than 1 */
4146
4147         if(sign) {
4148           int lp1 = lit+1;
4149
4150           size--;
4151
4152           if(lp1 == 0) {
4153             /* this means lit = 0xffffffff, or -1 */
4154
4155
4156             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4157             rFalseIfx.condition ^= 1;
4158             genSkipCond(&rFalseIfx,right,size,7);
4159             if(ifx) ifx->generated = 1;
4160             return;
4161           }
4162
4163           if(lit == 0) {
4164             int s = size;
4165
4166             if(rFalseIfx.condition) {
4167               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4168               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4169             }
4170
4171             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4172             while(size--)
4173               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4174
4175
4176             emitSKPZ;
4177             if(rFalseIfx.condition) {
4178               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4179               pic16_emitpLabel(truelbl->key);
4180             }else {
4181               rFalseIfx.condition ^= 1;
4182               genSkipCond(&rFalseIfx,right,s,7);
4183             }
4184
4185             if(ifx) ifx->generated = 1;
4186             return;
4187           }
4188
4189           if((size == 1) &&  (0 == (lp1&0xff))) {
4190             /* lower byte of signed word is zero */
4191             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4192             i = ((lp1 >> 8) & 0xff) ^0x80;
4193             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4194             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4195             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4196             rFalseIfx.condition ^= 1;
4197             genSkipc(&rFalseIfx);
4198
4199
4200             if(ifx) ifx->generated = 1;
4201             return;
4202           }
4203
4204           if(lit & (0x80 << (size*8))) {
4205             /* Lit is less than zero */
4206             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4207             //rFalseIfx.condition ^= 1;
4208             //genSkipCond(&rFalseIfx,left,size,7);
4209             //rFalseIfx.condition ^= 1;
4210             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4211             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4212
4213             if(rFalseIfx.condition)
4214               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4215             else
4216               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4217
4218
4219           } else {
4220             /* Lit is greater than or equal to zero */
4221             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4222             //rFalseIfx.condition ^= 1;
4223             //genSkipCond(&rFalseIfx,right,size,7);
4224             //rFalseIfx.condition ^= 1;
4225
4226             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4227             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4228
4229             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4230             if(rFalseIfx.condition)
4231               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4232             else
4233               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4234
4235           }
4236
4237
4238           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4239           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4240
4241           while(size--) {
4242
4243             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4244             emitSKPNZ;
4245             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4246           }
4247           rFalseIfx.condition ^= 1;
4248           //rFalseIfx.condition = 1;
4249           genSkipc(&rFalseIfx);
4250
4251           pic16_emitpLabel(truelbl->key);
4252
4253           if(ifx) ifx->generated = 1;
4254           return;
4255           // end of if (sign)
4256         } else {
4257
4258           /* compare word or long to an unsigned literal on the right.*/
4259
4260
4261           size--;
4262           if(lit < 0xff) {
4263             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4264             switch (lit) {
4265             case 0:
4266               break; /* handled above */
4267 /*
4268             case 0xff:
4269               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4270               while(size--)
4271                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4272               genSkipz2(&rFalseIfx,0);
4273               break;
4274 */
4275             default:
4276               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4277               while(--size)
4278                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4279
4280               emitSKPZ;
4281               if(rFalseIfx.condition)
4282                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4283               else
4284                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4285
4286
4287               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4288               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4289
4290               rFalseIfx.condition ^= 1;
4291               genSkipc(&rFalseIfx);
4292             }
4293
4294             pic16_emitpLabel(truelbl->key);
4295
4296             if(ifx) ifx->generated = 1;
4297             return;
4298           }
4299
4300
4301           lit++;
4302           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4303           i = (lit >> (size*8)) & 0xff;
4304
4305           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4306           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4307
4308           while(size--) {
4309             i = (lit >> (size*8)) & 0xff;
4310
4311             if(i) {
4312               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4313               emitSKPNZ;
4314               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4315             } else {
4316               /* this byte of the lit is zero, 
4317                *if it's not the last then OR in the variable */
4318               if(size)
4319                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4320             }
4321           }
4322
4323
4324           pic16_emitpLabel(lbl->key);
4325
4326           rFalseIfx.condition ^= 1;
4327           genSkipc(&rFalseIfx);
4328         }
4329
4330         if(sign)
4331           pic16_emitpLabel(truelbl->key);
4332         if(ifx) ifx->generated = 1;
4333         return;
4334       }
4335     }
4336     /* Compare two variables */
4337
4338     DEBUGpic16_emitcode(";sign","%d",sign);
4339
4340     size--;
4341     if(sign) {
4342       /* Sigh. thus sucks... */
4343       if(size) {
4344         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4345         pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
4346         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4347         pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
4348         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4349         pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
4350       } else {
4351         /* Signed char comparison */
4352         /* Special thanks to Nikolai Golovchenko for this snippet */
4353         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4354         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4355         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4356         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4357         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4358         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4359
4360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4361         genSkipc(&rFalseIfx);
4362           
4363         if(ifx) ifx->generated = 1;
4364         return;
4365       }
4366
4367     } else {
4368
4369       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4370       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4371     }
4372
4373
4374     /* The rest of the bytes of a multi-byte compare */
4375     while (size) {
4376
4377       emitSKPZ;
4378       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4379       size--;
4380
4381       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4382       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4383
4384
4385     }
4386
4387     pic16_emitpLabel(lbl->key);
4388
4389     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4390     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4391         (AOP_TYPE(result) == AOP_REG)) {
4392       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4393       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4394     } else {
4395       genSkipc(&rFalseIfx);
4396     }         
4397     //genSkipc(&rFalseIfx);
4398     if(ifx) ifx->generated = 1;
4399
4400     return;
4401
4402   }
4403
4404   // check_carry:
4405   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4407     pic16_outBitC(result);
4408   } else {
4409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4410     /* if the result is used in the next
4411        ifx conditional branch then generate
4412        code a little differently */
4413     if (ifx )
4414       genIfxJump (ifx,"c");
4415     else
4416       pic16_outBitC(result);
4417     /* leave the result in acc */
4418   }
4419
4420 }
4421
4422 /*-----------------------------------------------------------------*/
4423 /* genCmpGt :- greater than comparison                             */
4424 /*-----------------------------------------------------------------*/
4425 static void genCmpGt (iCode *ic, iCode *ifx)
4426 {
4427     operand *left, *right, *result;
4428     sym_link *letype , *retype;
4429     int sign ;
4430
4431     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4432     left = IC_LEFT(ic);
4433     right= IC_RIGHT(ic);
4434     result = IC_RESULT(ic);
4435
4436     letype = getSpec(operandType(left));
4437     retype =getSpec(operandType(right));
4438     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4439     /* assign the amsops */
4440     pic16_aopOp (left,ic,FALSE);
4441     pic16_aopOp (right,ic,FALSE);
4442     pic16_aopOp (result,ic,TRUE);
4443
4444     genCmp(right, left, result, ifx, sign);
4445
4446     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4447     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4448     pic16_freeAsmop(result,NULL,ic,TRUE); 
4449 }
4450
4451 /*-----------------------------------------------------------------*/
4452 /* genCmpLt - less than comparisons                                */
4453 /*-----------------------------------------------------------------*/
4454 static void genCmpLt (iCode *ic, iCode *ifx)
4455 {
4456     operand *left, *right, *result;
4457     sym_link *letype , *retype;
4458     int sign ;
4459
4460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4461     left = IC_LEFT(ic);
4462     right= IC_RIGHT(ic);
4463     result = IC_RESULT(ic);
4464
4465     letype = getSpec(operandType(left));
4466     retype =getSpec(operandType(right));
4467     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4468
4469     /* assign the amsops */
4470     pic16_aopOp (left,ic,FALSE);
4471     pic16_aopOp (right,ic,FALSE);
4472     pic16_aopOp (result,ic,TRUE);
4473
4474     genCmp(left, right, result, ifx, sign);
4475
4476     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4477     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4478     pic16_freeAsmop(result,NULL,ic,TRUE); 
4479 }
4480
4481 /*-----------------------------------------------------------------*/
4482 /* genc16bit2lit - compare a 16 bit value to a literal             */
4483 /*-----------------------------------------------------------------*/
4484 static void genc16bit2lit(operand *op, int lit, int offset)
4485 {
4486   int i;
4487
4488   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4489   if( (lit&0xff) == 0) 
4490     i=1;
4491   else
4492     i=0;
4493
4494   switch( BYTEofLONG(lit,i)) { 
4495   case 0:
4496     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4497     break;
4498   case 1:
4499     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4500     break;
4501   case 0xff:
4502     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4503     break;
4504   default:
4505     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4506     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4507   }
4508
4509   i ^= 1;
4510
4511   switch( BYTEofLONG(lit,i)) { 
4512   case 0:
4513     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4514     break;
4515   case 1:
4516     emitSKPNZ;
4517     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4518     break;
4519   case 0xff:
4520     emitSKPNZ;
4521     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4522     break;
4523   default:
4524     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4525     emitSKPNZ;
4526     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4527
4528   }
4529
4530 }
4531
4532 /*-----------------------------------------------------------------*/
4533 /* gencjneshort - compare and jump if not equal                    */
4534 /*-----------------------------------------------------------------*/
4535 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4536 {
4537   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4538   int offset = 0;
4539   int res_offset = 0;  /* the result may be a different size then left or right */
4540   int res_size = AOP_SIZE(result);
4541   resolvedIfx rIfx;
4542   symbol *lbl;
4543
4544   unsigned long lit = 0L;
4545   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4546   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4547   if(result)
4548     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4549   resolveIfx(&rIfx,ifx);
4550   lbl =  newiTempLabel(NULL);
4551
4552
4553   /* if the left side is a literal or 
4554      if the right is in a pointer register and left 
4555      is not */
4556   if ((AOP_TYPE(left) == AOP_LIT) || 
4557       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4558     operand *t = right;
4559     right = left;
4560     left = t;
4561   }
4562   if(AOP_TYPE(right) == AOP_LIT)
4563     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4564
4565   /* if the right side is a literal then anything goes */
4566   if (AOP_TYPE(right) == AOP_LIT &&
4567       AOP_TYPE(left) != AOP_DIR ) {
4568     switch(size) {
4569     case 2:
4570       genc16bit2lit(left, lit, 0);
4571       emitSKPNZ;
4572       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4573       break;
4574     default:
4575       while (size--) {
4576         if(lit & 0xff) {
4577           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4578           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4579         } else {
4580           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4581         }
4582
4583         emitSKPNZ;
4584         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4585         offset++;
4586         if(res_offset < res_size-1)
4587           res_offset++;
4588         lit >>= 8;
4589       }
4590       break;
4591     }
4592   }
4593
4594   /* if the right side is in a register or in direct space or
4595      if the left is a pointer register & right is not */    
4596   else if (AOP_TYPE(right) == AOP_REG ||
4597            AOP_TYPE(right) == AOP_DIR || 
4598            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4599            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4600     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4601     int lbl_key = lbl->key;
4602
4603     if(result) {
4604       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4605       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4606     }else {
4607       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4608       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4609               __FUNCTION__,__LINE__);
4610       return;
4611     }
4612
4613 /*     switch(size) { */
4614 /*     case 2: */
4615 /*       genc16bit2lit(left, lit, 0); */
4616 /*       emitSKPNZ; */
4617 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4618 /*       break; */
4619 /*     default: */
4620     while (size--) {
4621       int emit_skip=1;
4622       if((AOP_TYPE(left) == AOP_DIR) && 
4623          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4624
4625         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4626         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4627
4628       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4629             
4630         switch (lit & 0xff) {
4631         case 0:
4632           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4633           break;
4634         case 1:
4635           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4636           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4637           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4638           emit_skip=0;
4639           break;
4640         case 0xff:
4641           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4642           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4643           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4644           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4645           emit_skip=0;
4646           break;
4647         default:
4648           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4649           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4650         }
4651         lit >>= 8;
4652
4653       } else {
4654         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4655       }
4656       if(emit_skip) {
4657         if(AOP_TYPE(result) == AOP_CRY) {
4658           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4659           if(rIfx.condition)
4660             emitSKPNZ;
4661           else
4662             emitSKPZ;
4663           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4664         } else {
4665           /* fix me. probably need to check result size too */
4666           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4667           if(rIfx.condition)
4668             emitSKPZ;
4669           else
4670             emitSKPNZ;
4671           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4672           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4673         }
4674         if(ifx)
4675           ifx->generated=1;
4676       }
4677       emit_skip++;
4678       offset++;
4679       if(res_offset < res_size-1)
4680         res_offset++;
4681     }
4682 /*       break; */
4683 /*     } */
4684   } else if(AOP_TYPE(right) == AOP_REG &&
4685             AOP_TYPE(left) != AOP_DIR){
4686
4687     while(size--) {
4688       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4689       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4690       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4691       if(rIfx.condition)
4692         emitSKPNZ;
4693       else
4694         emitSKPZ;
4695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4696       offset++;
4697       if(res_offset < res_size-1)
4698         res_offset++;
4699     }
4700       
4701   }else{
4702     /* right is a pointer reg need both a & b */
4703     while(size--) {
4704       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4705       if(strcmp(l,"b"))
4706         pic16_emitcode("mov","b,%s",l);
4707       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4708       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4709       offset++;
4710     }
4711   }
4712
4713   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4714   if(!rIfx.condition)
4715     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4716
4717   pic16_emitpLabel(lbl->key);
4718
4719   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4720
4721   if(ifx)
4722     ifx->generated = 1;
4723 }
4724
4725 #if 0
4726 /*-----------------------------------------------------------------*/
4727 /* gencjne - compare and jump if not equal                         */
4728 /*-----------------------------------------------------------------*/
4729 static void gencjne(operand *left, operand *right, iCode *ifx)
4730 {
4731     symbol *tlbl  = newiTempLabel(NULL);
4732
4733     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4734     gencjneshort(left, right, lbl);
4735
4736     pic16_emitcode("mov","a,%s",one);
4737     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4738     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4739     pic16_emitcode("clr","a");
4740     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4741
4742     pic16_emitpLabel(lbl->key);
4743     pic16_emitpLabel(tlbl->key);
4744
4745 }
4746 #endif
4747
4748 /*-----------------------------------------------------------------*/
4749 /* genCmpEq - generates code for equal to                          */
4750 /*-----------------------------------------------------------------*/
4751 static void genCmpEq (iCode *ic, iCode *ifx)
4752 {
4753     operand *left, *right, *result;
4754     unsigned long lit = 0L;
4755     int size,offset=0;
4756
4757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4758
4759     if(ifx)
4760       DEBUGpic16_emitcode ("; ifx is non-null","");
4761     else
4762       DEBUGpic16_emitcode ("; ifx is null","");
4763
4764     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4765     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4766     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4767
4768     size = max(AOP_SIZE(left),AOP_SIZE(right));
4769
4770     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4771
4772     /* if literal, literal on the right or 
4773     if the right is in a pointer register and left 
4774     is not */
4775     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4776         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4777       operand *tmp = right ;
4778       right = left;
4779       left = tmp;
4780     }
4781
4782
4783     if(ifx && !AOP_SIZE(result)){
4784         symbol *tlbl;
4785         /* if they are both bit variables */
4786         if (AOP_TYPE(left) == AOP_CRY &&
4787             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4788             if(AOP_TYPE(right) == AOP_LIT){
4789                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4790                 if(lit == 0L){
4791                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4792                     pic16_emitcode("cpl","c");
4793                 } else if(lit == 1L) {
4794                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4795                 } else {
4796                     pic16_emitcode("clr","c");
4797                 }
4798                 /* AOP_TYPE(right) == AOP_CRY */
4799             } else {
4800                 symbol *lbl = newiTempLabel(NULL);
4801                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4802                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4803                 pic16_emitcode("cpl","c");
4804                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4805             }
4806             /* if true label then we jump if condition
4807             supplied is true */
4808             tlbl = newiTempLabel(NULL);
4809             if ( IC_TRUE(ifx) ) {
4810                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4811                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4812             } else {
4813                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4814                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4815             }
4816             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4817
4818             {
4819               /* left and right are both bit variables, result is carry */
4820               resolvedIfx rIfx;
4821               
4822               resolveIfx(&rIfx,ifx);
4823
4824               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4825               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4826               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4827               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4828               genSkipz2(&rIfx,0);
4829             }
4830         } else {
4831
4832           /* They're not both bit variables. Is the right a literal? */
4833           if(AOP_TYPE(right) == AOP_LIT) {
4834             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4835             
4836             switch(size) {
4837
4838             case 1:
4839               switch(lit & 0xff) {
4840               case 1:
4841                 if ( IC_TRUE(ifx) ) {
4842                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4843                   emitSKPNZ;
4844                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4845                 } else {
4846                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4847                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4848                 }
4849                 break;
4850               case 0xff:
4851                 if ( IC_TRUE(ifx) ) {
4852                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4853                   emitSKPNZ;
4854                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4855                 } else {
4856                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4857                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4858                 }
4859                 break;
4860               default:
4861                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4862                 if(lit)
4863                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4864                 genSkip(ifx,'z');
4865               }
4866
4867
4868               /* end of size == 1 */
4869               break;
4870               
4871             case 2:
4872               genc16bit2lit(left,lit,offset);
4873               genSkip(ifx,'z');
4874               break;
4875               /* end of size == 2 */
4876
4877             default:
4878               /* size is 4 */
4879               if(lit==0) {
4880                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4881                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4882                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4883                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4884
4885               } else {
4886
4887                 /* search for patterns that can be optimized */
4888
4889                 genc16bit2lit(left,lit,0);
4890                 lit >>= 16;
4891                 if(lit) {
4892                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4893                   //genSkip(ifx,'z');
4894                   genc16bit2lit(left,lit,2);
4895                 } else {
4896                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4897                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4898
4899                 }
4900                 
4901               }
4902
4903               genSkip(ifx,'z');
4904             }
4905           
4906             ifx->generated = 1;
4907             goto release ;
4908             
4909
4910           } else if(AOP_TYPE(right) == AOP_CRY ) {
4911             /* we know the left is not a bit, but that the right is */
4912             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4913             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4914                       pic16_popGet(AOP(right),offset));
4915             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4916
4917             /* if the two are equal, then W will be 0 and the Z bit is set
4918              * we could test Z now, or go ahead and check the high order bytes if
4919              * the variable we're comparing is larger than a byte. */
4920
4921             while(--size)
4922               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4923
4924             if ( IC_TRUE(ifx) ) {
4925               emitSKPNZ;
4926               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4927               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4928             } else {
4929               emitSKPZ;
4930               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4931               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4932             }
4933
4934           } else {
4935             /* They're both variables that are larger than bits */
4936             int s = size;
4937
4938             tlbl = newiTempLabel(NULL);
4939
4940             while(size--) {
4941               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4942               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4943
4944               if ( IC_TRUE(ifx) ) {
4945                 if(size) {
4946                   emitSKPZ;
4947                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4948                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4949                 } else {
4950                   emitSKPNZ;
4951                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4952                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4953                 }
4954               } else {
4955                 emitSKPZ;
4956                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4957                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4958               }
4959               offset++;
4960             }
4961             if(s>1 && IC_TRUE(ifx)) {
4962               pic16_emitpLabel(tlbl->key);
4963               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4964             }
4965           }
4966         }
4967         /* mark the icode as generated */
4968         ifx->generated = 1;
4969         goto release ;
4970     }
4971
4972     /* if they are both bit variables */
4973     if (AOP_TYPE(left) == AOP_CRY &&
4974         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4975         if(AOP_TYPE(right) == AOP_LIT){
4976             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4977             if(lit == 0L){
4978                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4979                 pic16_emitcode("cpl","c");
4980             } else if(lit == 1L) {
4981                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4982             } else {
4983                 pic16_emitcode("clr","c");
4984             }
4985             /* AOP_TYPE(right) == AOP_CRY */
4986         } else {
4987             symbol *lbl = newiTempLabel(NULL);
4988             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4989             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4990             pic16_emitcode("cpl","c");
4991             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4992         }
4993         /* c = 1 if egal */
4994         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4995             pic16_outBitC(result);
4996             goto release ;
4997         }
4998         if (ifx) {
4999             genIfxJump (ifx,"c");
5000             goto release ;
5001         }
5002         /* if the result is used in an arithmetic operation
5003         then put the result in place */
5004         pic16_outBitC(result);
5005     } else {
5006       
5007       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5008       gencjne(left,right,result,ifx);
5009 /*
5010       if(ifx) 
5011         gencjne(left,right,newiTempLabel(NULL));
5012       else {
5013         if(IC_TRUE(ifx)->key)
5014           gencjne(left,right,IC_TRUE(ifx)->key);
5015         else
5016           gencjne(left,right,IC_FALSE(ifx)->key);
5017         ifx->generated = 1;
5018         goto release ;
5019       }
5020       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5021         pic16_aopPut(AOP(result),"a",0);
5022         goto release ;
5023       }
5024
5025       if (ifx) {
5026         genIfxJump (ifx,"a");
5027         goto release ;
5028       }
5029 */
5030       /* if the result is used in an arithmetic operation
5031          then put the result in place */
5032 /*
5033       if (AOP_TYPE(result) != AOP_CRY) 
5034         pic16_outAcc(result);
5035 */
5036       /* leave the result in acc */
5037     }
5038
5039 release:
5040     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5041     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5042     pic16_freeAsmop(result,NULL,ic,TRUE);
5043 }
5044
5045 /*-----------------------------------------------------------------*/
5046 /* ifxForOp - returns the icode containing the ifx for operand     */
5047 /*-----------------------------------------------------------------*/
5048 static iCode *ifxForOp ( operand *op, iCode *ic )
5049 {
5050     /* if true symbol then needs to be assigned */
5051     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5052     if (IS_TRUE_SYMOP(op))
5053         return NULL ;
5054
5055     /* if this has register type condition and
5056     the next instruction is ifx with the same operand
5057     and live to of the operand is upto the ifx only then */
5058     if (ic->next &&
5059         ic->next->op == IFX &&
5060         IC_COND(ic->next)->key == op->key &&
5061         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5062         return ic->next;
5063
5064     if (ic->next &&
5065         ic->next->op == IFX &&
5066         IC_COND(ic->next)->key == op->key) {
5067       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5068       return ic->next;
5069     }
5070
5071     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5072     if (ic->next &&
5073         ic->next->op == IFX)
5074       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5075
5076     if (ic->next &&
5077         ic->next->op == IFX &&
5078         IC_COND(ic->next)->key == op->key) {
5079       DEBUGpic16_emitcode ("; "," key is okay");
5080       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5081                            OP_SYMBOL(op)->liveTo,
5082                            ic->next->seq);
5083     }
5084
5085
5086     return NULL;
5087 }
5088 /*-----------------------------------------------------------------*/
5089 /* genAndOp - for && operation                                     */
5090 /*-----------------------------------------------------------------*/
5091 static void genAndOp (iCode *ic)
5092 {
5093     operand *left,*right, *result;
5094 /*     symbol *tlbl; */
5095
5096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5097     /* note here that && operations that are in an
5098     if statement are taken away by backPatchLabels
5099     only those used in arthmetic operations remain */
5100     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5101     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5102     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5103
5104     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5105
5106     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5107     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5108     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5109
5110     /* if both are bit variables */
5111 /*     if (AOP_TYPE(left) == AOP_CRY && */
5112 /*         AOP_TYPE(right) == AOP_CRY ) { */
5113 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5114 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5115 /*         pic16_outBitC(result); */
5116 /*     } else { */
5117 /*         tlbl = newiTempLabel(NULL); */
5118 /*         pic16_toBoolean(left);     */
5119 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5120 /*         pic16_toBoolean(right); */
5121 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5122 /*         pic16_outBitAcc(result); */
5123 /*     } */
5124
5125     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5126     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5127     pic16_freeAsmop(result,NULL,ic,TRUE);
5128 }
5129
5130
5131 /*-----------------------------------------------------------------*/
5132 /* genOrOp - for || operation                                      */
5133 /*-----------------------------------------------------------------*/
5134 /*
5135   tsd pic port -
5136   modified this code, but it doesn't appear to ever get called
5137 */
5138
5139 static void genOrOp (iCode *ic)
5140 {
5141     operand *left,*right, *result;
5142     symbol *tlbl;
5143
5144     /* note here that || operations that are in an
5145     if statement are taken away by backPatchLabels
5146     only those used in arthmetic operations remain */
5147     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5148     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5149     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5150     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5151
5152     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5153
5154     /* if both are bit variables */
5155     if (AOP_TYPE(left) == AOP_CRY &&
5156         AOP_TYPE(right) == AOP_CRY ) {
5157       pic16_emitcode("clrc","");
5158       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5159                AOP(left)->aopu.aop_dir,
5160                AOP(left)->aopu.aop_dir);
5161       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5162                AOP(right)->aopu.aop_dir,
5163                AOP(right)->aopu.aop_dir);
5164       pic16_emitcode("setc","");
5165
5166     } else {
5167         tlbl = newiTempLabel(NULL);
5168         pic16_toBoolean(left);
5169         emitSKPZ;
5170         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5171         pic16_toBoolean(right);
5172         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5173
5174         pic16_outBitAcc(result);
5175     }
5176
5177     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5178     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5179     pic16_freeAsmop(result,NULL,ic,TRUE);            
5180 }
5181
5182 /*-----------------------------------------------------------------*/
5183 /* isLiteralBit - test if lit == 2^n                               */
5184 /*-----------------------------------------------------------------*/
5185 static int isLiteralBit(unsigned long lit)
5186 {
5187     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5188     0x100L,0x200L,0x400L,0x800L,
5189     0x1000L,0x2000L,0x4000L,0x8000L,
5190     0x10000L,0x20000L,0x40000L,0x80000L,
5191     0x100000L,0x200000L,0x400000L,0x800000L,
5192     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5193     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5194     int idx;
5195     
5196     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5197     for(idx = 0; idx < 32; idx++)
5198         if(lit == pw[idx])
5199             return idx+1;
5200     return 0;
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* continueIfTrue -                                                */
5205 /*-----------------------------------------------------------------*/
5206 static void continueIfTrue (iCode *ic)
5207 {
5208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5209     if(IC_TRUE(ic))
5210         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5211     ic->generated = 1;
5212 }
5213
5214 /*-----------------------------------------------------------------*/
5215 /* jmpIfTrue -                                                     */
5216 /*-----------------------------------------------------------------*/
5217 static void jumpIfTrue (iCode *ic)
5218 {
5219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5220     if(!IC_TRUE(ic))
5221         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5222     ic->generated = 1;
5223 }
5224
5225 /*-----------------------------------------------------------------*/
5226 /* jmpTrueOrFalse -                                                */
5227 /*-----------------------------------------------------------------*/
5228 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5229 {
5230     // ugly but optimized by peephole
5231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5232     if(IC_TRUE(ic)){
5233         symbol *nlbl = newiTempLabel(NULL);
5234         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5235         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5236         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5237         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5238     }
5239     else{
5240         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5241         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5242     }
5243     ic->generated = 1;
5244 }
5245
5246 /*-----------------------------------------------------------------*/
5247 /* genAnd  - code for and                                          */
5248 /*-----------------------------------------------------------------*/
5249 static void genAnd (iCode *ic, iCode *ifx)
5250 {
5251   operand *left, *right, *result;
5252   int size, offset=0;  
5253   unsigned long lit = 0L;
5254   int bytelit = 0;
5255   resolvedIfx rIfx;
5256
5257
5258   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5259   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5260   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5261   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5262
5263   resolveIfx(&rIfx,ifx);
5264
5265   /* if left is a literal & right is not then exchange them */
5266   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5267       AOP_NEEDSACC(left)) {
5268     operand *tmp = right ;
5269     right = left;
5270     left = tmp;
5271   }
5272
5273   /* if result = right then exchange them */
5274   if(pic16_sameRegs(AOP(result),AOP(right))){
5275     operand *tmp = right ;
5276     right = left;
5277     left = tmp;
5278   }
5279
5280   /* if right is bit then exchange them */
5281   if (AOP_TYPE(right) == AOP_CRY &&
5282       AOP_TYPE(left) != AOP_CRY){
5283     operand *tmp = right ;
5284     right = left;
5285     left = tmp;
5286   }
5287   if(AOP_TYPE(right) == AOP_LIT)
5288     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5289
5290   size = AOP_SIZE(result);
5291
5292   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5293
5294   // if(bit & yy)
5295   // result = bit & yy;
5296   if (AOP_TYPE(left) == AOP_CRY){
5297     // c = bit & literal;
5298     if(AOP_TYPE(right) == AOP_LIT){
5299       if(lit & 1) {
5300         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5301           // no change
5302           goto release;
5303         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5304       } else {
5305         // bit(result) = 0;
5306         if(size && (AOP_TYPE(result) == AOP_CRY)){
5307           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5308           goto release;
5309         }
5310         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5311           jumpIfTrue(ifx);
5312           goto release;
5313         }
5314         pic16_emitcode("clr","c");
5315       }
5316     } else {
5317       if (AOP_TYPE(right) == AOP_CRY){
5318         // c = bit & bit;
5319         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5320         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5321       } else {
5322         // c = bit & val;
5323         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5324         // c = lsb
5325         pic16_emitcode("rrc","a");
5326         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5327       }
5328     }
5329     // bit = c
5330     // val = c
5331     if(size)
5332       pic16_outBitC(result);
5333     // if(bit & ...)
5334     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5335       genIfxJump(ifx, "c");           
5336     goto release ;
5337   }
5338
5339   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5340   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5341   if((AOP_TYPE(right) == AOP_LIT) &&
5342      (AOP_TYPE(result) == AOP_CRY) &&
5343      (AOP_TYPE(left) != AOP_CRY)){
5344     int posbit = isLiteralBit(lit);
5345     /* left &  2^n */
5346     if(posbit){
5347       posbit--;
5348       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5349       // bit = left & 2^n
5350       if(size)
5351         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5352       // if(left &  2^n)
5353       else{
5354         if(ifx){
5355 /*
5356           if(IC_TRUE(ifx)) {
5357             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5358             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5359           } else {
5360             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5361             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5362           }
5363 */
5364           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5365                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5366           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5367           
5368           ifx->generated = 1;
5369         }
5370         goto release;
5371       }
5372     } else {
5373       symbol *tlbl = newiTempLabel(NULL);
5374       int sizel = AOP_SIZE(left);
5375       if(size)
5376         pic16_emitcode("setb","c");
5377       while(sizel--){
5378         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5379           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5380           // byte ==  2^n ?
5381           if((posbit = isLiteralBit(bytelit)) != 0)
5382             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5383           else{
5384             if(bytelit != 0x0FFL)
5385               pic16_emitcode("anl","a,%s",
5386                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5387             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5388           }
5389         }
5390         offset++;
5391       }
5392       // bit = left & literal
5393       if(size){
5394         pic16_emitcode("clr","c");
5395         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5396       }
5397       // if(left & literal)
5398       else{
5399         if(ifx)
5400           jmpTrueOrFalse(ifx, tlbl);
5401         goto release ;
5402       }
5403     }
5404     pic16_outBitC(result);
5405     goto release ;
5406   }
5407
5408   /* if left is same as result */
5409   if(pic16_sameRegs(AOP(result),AOP(left))){
5410     int know_W = -1;
5411     for(;size--; offset++,lit>>=8) {
5412       if(AOP_TYPE(right) == AOP_LIT){
5413         switch(lit & 0xff) {
5414         case 0x00:
5415           /*  and'ing with 0 has clears the result */
5416           pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5417           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5418           break;
5419         case 0xff:
5420           /* and'ing with 0xff is a nop when the result and left are the same */
5421           break;
5422
5423         default:
5424           {
5425             int p = my_powof2( (~lit) & 0xff );
5426             if(p>=0) {
5427               /* only one bit is set in the literal, so use a bcf instruction */
5428               pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5429               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5430
5431             } else {
5432               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5433               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5434               if(know_W != (lit&0xff))
5435                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5436               know_W = lit &0xff;
5437               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5438             }
5439           }    
5440         }
5441       } else {
5442         if (AOP_TYPE(left) == AOP_ACC) {
5443           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5444         } else {                    
5445           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5446           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5447
5448         }
5449       }
5450     }
5451
5452   } else {
5453     // left & result in different registers
5454     if(AOP_TYPE(result) == AOP_CRY){
5455       // result = bit
5456       // if(size), result in bit
5457       // if(!size && ifx), conditional oper: if(left & right)
5458       symbol *tlbl = newiTempLabel(NULL);
5459       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5460       if(size)
5461         pic16_emitcode("setb","c");
5462       while(sizer--){
5463         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5464         pic16_emitcode("anl","a,%s",
5465                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5466         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5467         offset++;
5468       }
5469       if(size){
5470         CLRC;
5471         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5472         pic16_outBitC(result);
5473       } else if(ifx)
5474         jmpTrueOrFalse(ifx, tlbl);
5475     } else {
5476       for(;(size--);offset++) {
5477         // normal case
5478         // result = left & right
5479         if(AOP_TYPE(right) == AOP_LIT){
5480           int t = (lit >> (offset*8)) & 0x0FFL;
5481           switch(t) { 
5482           case 0x00:
5483             pic16_emitcode("clrf","%s",
5484                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5485             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5486             break;
5487           case 0xff:
5488             pic16_emitcode("movf","%s,w",
5489                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5490             pic16_emitcode("movwf","%s",
5491                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5492             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5493             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5494             break;
5495           default:
5496             pic16_emitcode("movlw","0x%x",t);
5497             pic16_emitcode("andwf","%s,w",
5498                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5499             pic16_emitcode("movwf","%s",
5500                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5501               
5502             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5503             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5504             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5505           }
5506           continue;
5507         }
5508
5509         if (AOP_TYPE(left) == AOP_ACC) {
5510           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5511           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5512         } else {
5513           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5514           pic16_emitcode("andwf","%s,w",
5515                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5516           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5517           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5518         }
5519         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5520         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5521       }
5522     }
5523   }
5524
5525   release :
5526     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5527   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5528   pic16_freeAsmop(result,NULL,ic,TRUE);     
5529 }
5530
5531 /*-----------------------------------------------------------------*/
5532 /* genOr  - code for or                                            */
5533 /*-----------------------------------------------------------------*/
5534 static void genOr (iCode *ic, iCode *ifx)
5535 {
5536     operand *left, *right, *result;
5537     int size, offset=0;
5538     unsigned long lit = 0L;
5539
5540     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5541
5542     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5543     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5544     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5545
5546     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5547
5548     /* if left is a literal & right is not then exchange them */
5549     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5550         AOP_NEEDSACC(left)) {
5551         operand *tmp = right ;
5552         right = left;
5553         left = tmp;
5554     }
5555
5556     /* if result = right then exchange them */
5557     if(pic16_sameRegs(AOP(result),AOP(right))){
5558         operand *tmp = right ;
5559         right = left;
5560         left = tmp;
5561     }
5562
5563     /* if right is bit then exchange them */
5564     if (AOP_TYPE(right) == AOP_CRY &&
5565         AOP_TYPE(left) != AOP_CRY){
5566         operand *tmp = right ;
5567         right = left;
5568         left = tmp;
5569     }
5570
5571     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5572
5573     if(AOP_TYPE(right) == AOP_LIT)
5574         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5575
5576     size = AOP_SIZE(result);
5577
5578     // if(bit | yy)
5579     // xx = bit | yy;
5580     if (AOP_TYPE(left) == AOP_CRY){
5581         if(AOP_TYPE(right) == AOP_LIT){
5582             // c = bit & literal;
5583             if(lit){
5584                 // lit != 0 => result = 1
5585                 if(AOP_TYPE(result) == AOP_CRY){
5586                   if(size)
5587                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5588                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5589                   //     AOP(result)->aopu.aop_dir,
5590                   //     AOP(result)->aopu.aop_dir);
5591                     else if(ifx)
5592                         continueIfTrue(ifx);
5593                     goto release;
5594                 }
5595             } else {
5596                 // lit == 0 => result = left
5597                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5598                     goto release;
5599                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5600             }
5601         } else {
5602             if (AOP_TYPE(right) == AOP_CRY){
5603               if(pic16_sameRegs(AOP(result),AOP(left))){
5604                 // c = bit | bit;
5605                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5606                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5607                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5608
5609                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5610                          AOP(result)->aopu.aop_dir,
5611                          AOP(result)->aopu.aop_dir);
5612                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5613                          AOP(right)->aopu.aop_dir,
5614                          AOP(right)->aopu.aop_dir);
5615                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5616                          AOP(result)->aopu.aop_dir,
5617                          AOP(result)->aopu.aop_dir);
5618               } else {
5619                 if( AOP_TYPE(result) == AOP_ACC) {
5620                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5621                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5622                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5623                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5624
5625                 } else {
5626
5627                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5628                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5629                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5630                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5631
5632                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5633                                  AOP(result)->aopu.aop_dir,
5634                                  AOP(result)->aopu.aop_dir);
5635                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5636                                  AOP(right)->aopu.aop_dir,
5637                                  AOP(right)->aopu.aop_dir);
5638                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5639                                  AOP(left)->aopu.aop_dir,
5640                                  AOP(left)->aopu.aop_dir);
5641                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5642                                  AOP(result)->aopu.aop_dir,
5643                                  AOP(result)->aopu.aop_dir);
5644                 }
5645               }
5646             } else {
5647                 // c = bit | val;
5648                 symbol *tlbl = newiTempLabel(NULL);
5649                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5650
5651
5652                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5653                 if( AOP_TYPE(right) == AOP_ACC) {
5654                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5655                   emitSKPNZ;
5656                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5657                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5658                 }
5659
5660
5661
5662                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5663                     pic16_emitcode(";XXX setb","c");
5664                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5665                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5666                 pic16_toBoolean(right);
5667                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5668                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5669                     jmpTrueOrFalse(ifx, tlbl);
5670                     goto release;
5671                 } else {
5672                     CLRC;
5673                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5674                 }
5675             }
5676         }
5677         // bit = c
5678         // val = c
5679         if(size)
5680             pic16_outBitC(result);
5681         // if(bit | ...)
5682         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5683             genIfxJump(ifx, "c");           
5684         goto release ;
5685     }
5686
5687     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5688     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5689     if((AOP_TYPE(right) == AOP_LIT) &&
5690        (AOP_TYPE(result) == AOP_CRY) &&
5691        (AOP_TYPE(left) != AOP_CRY)){
5692         if(lit){
5693           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5694             // result = 1
5695             if(size)
5696                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5697             else 
5698                 continueIfTrue(ifx);
5699             goto release;
5700         } else {
5701           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5702             // lit = 0, result = boolean(left)
5703             if(size)
5704                 pic16_emitcode(";XXX setb","c");
5705             pic16_toBoolean(right);
5706             if(size){
5707                 symbol *tlbl = newiTempLabel(NULL);
5708                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5709                 CLRC;
5710                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5711             } else {
5712                 genIfxJump (ifx,"a");
5713                 goto release;
5714             }
5715         }
5716         pic16_outBitC(result);
5717         goto release ;
5718     }
5719
5720     /* if left is same as result */
5721     if(pic16_sameRegs(AOP(result),AOP(left))){
5722       int know_W = -1;
5723       for(;size--; offset++,lit>>=8) {
5724         if(AOP_TYPE(right) == AOP_LIT){
5725           if((lit & 0xff) == 0)
5726             /*  or'ing with 0 has no effect */
5727             continue;
5728           else {
5729             int p = my_powof2(lit & 0xff);
5730             if(p>=0) {
5731               /* only one bit is set in the literal, so use a bsf instruction */
5732               pic16_emitpcode(POC_BSF,
5733                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5734             } else {
5735               if(know_W != (lit & 0xff))
5736                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5737               know_W = lit & 0xff;
5738               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5739             }
5740                     
5741           }
5742         } else {
5743           if (AOP_TYPE(left) == AOP_ACC) {
5744             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5745             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5746           } else {                  
5747             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5748             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5749
5750             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5751             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5752
5753           }
5754         }
5755       }
5756     } else {
5757         // left & result in different registers
5758         if(AOP_TYPE(result) == AOP_CRY){
5759             // result = bit
5760             // if(size), result in bit
5761             // if(!size && ifx), conditional oper: if(left | right)
5762             symbol *tlbl = newiTempLabel(NULL);
5763             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5764             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5765
5766
5767             if(size)
5768                 pic16_emitcode(";XXX setb","c");
5769             while(sizer--){
5770                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5771                 pic16_emitcode(";XXX orl","a,%s",
5772                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5773                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5774                 offset++;
5775             }
5776             if(size){
5777                 CLRC;
5778                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5779                 pic16_outBitC(result);
5780             } else if(ifx)
5781                 jmpTrueOrFalse(ifx, tlbl);
5782         } else for(;(size--);offset++){
5783           // normal case
5784           // result = left & right
5785           if(AOP_TYPE(right) == AOP_LIT){
5786             int t = (lit >> (offset*8)) & 0x0FFL;
5787             switch(t) { 
5788             case 0x00:
5789               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5790               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5791
5792               pic16_emitcode("movf","%s,w",
5793                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5794               pic16_emitcode("movwf","%s",
5795                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5796               break;
5797             default:
5798               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5799               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5800               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5801
5802               pic16_emitcode("movlw","0x%x",t);
5803               pic16_emitcode("iorwf","%s,w",
5804                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5805               pic16_emitcode("movwf","%s",
5806                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5807               
5808             }
5809             continue;
5810           }
5811
5812           // faster than result <- left, anl result,right
5813           // and better if result is SFR
5814           if (AOP_TYPE(left) == AOP_ACC) {
5815             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5816             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5817           } else {
5818             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5819             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5820
5821             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5822             pic16_emitcode("iorwf","%s,w",
5823                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5824           }
5825           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5826           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5827         }
5828     }
5829
5830 release :
5831     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5832     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5833     pic16_freeAsmop(result,NULL,ic,TRUE);     
5834 }
5835
5836 /*-----------------------------------------------------------------*/
5837 /* genXor - code for xclusive or                                   */
5838 /*-----------------------------------------------------------------*/
5839 static void genXor (iCode *ic, iCode *ifx)
5840 {
5841   operand *left, *right, *result;
5842   int size, offset=0;
5843   unsigned long lit = 0L;
5844
5845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5846
5847   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5848   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5849   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5850
5851   /* if left is a literal & right is not ||
5852      if left needs acc & right does not */
5853   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5854       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5855     operand *tmp = right ;
5856     right = left;
5857     left = tmp;
5858   }
5859
5860   /* if result = right then exchange them */
5861   if(pic16_sameRegs(AOP(result),AOP(right))){
5862     operand *tmp = right ;
5863     right = left;
5864     left = tmp;
5865   }
5866
5867   /* if right is bit then exchange them */
5868   if (AOP_TYPE(right) == AOP_CRY &&
5869       AOP_TYPE(left) != AOP_CRY){
5870     operand *tmp = right ;
5871     right = left;
5872     left = tmp;
5873   }
5874   if(AOP_TYPE(right) == AOP_LIT)
5875     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5876
5877   size = AOP_SIZE(result);
5878
5879   // if(bit ^ yy)
5880   // xx = bit ^ yy;
5881   if (AOP_TYPE(left) == AOP_CRY){
5882     if(AOP_TYPE(right) == AOP_LIT){
5883       // c = bit & literal;
5884       if(lit>>1){
5885         // lit>>1  != 0 => result = 1
5886         if(AOP_TYPE(result) == AOP_CRY){
5887           if(size)
5888             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
5889             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5890           else if(ifx)
5891             continueIfTrue(ifx);
5892           goto release;
5893         }
5894         pic16_emitcode("setb","c");
5895       } else{
5896         // lit == (0 or 1)
5897         if(lit == 0){
5898           // lit == 0, result = left
5899           if(size && pic16_sameRegs(AOP(result),AOP(left)))
5900             goto release;
5901           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5902         } else{
5903           // lit == 1, result = not(left)
5904           if(size && pic16_sameRegs(AOP(result),AOP(left))){
5905             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
5906             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
5907             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5908             goto release;
5909           } else {
5910             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5911             pic16_emitcode("cpl","c");
5912           }
5913         }
5914       }
5915
5916     } else {
5917       // right != literal
5918       symbol *tlbl = newiTempLabel(NULL);
5919       if (AOP_TYPE(right) == AOP_CRY){
5920         // c = bit ^ bit;
5921         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5922       }
5923       else{
5924         int sizer = AOP_SIZE(right);
5925         // c = bit ^ val
5926         // if val>>1 != 0, result = 1
5927         pic16_emitcode("setb","c");
5928         while(sizer){
5929           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
5930           if(sizer == 1)
5931             // test the msb of the lsb
5932             pic16_emitcode("anl","a,#0xfe");
5933           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5934           sizer--;
5935         }
5936         // val = (0,1)
5937         pic16_emitcode("rrc","a");
5938       }
5939       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5940       pic16_emitcode("cpl","c");
5941       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
5942     }
5943     // bit = c
5944     // val = c
5945     if(size)
5946       pic16_outBitC(result);
5947     // if(bit | ...)
5948     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5949       genIfxJump(ifx, "c");           
5950     goto release ;
5951   }
5952
5953   if(pic16_sameRegs(AOP(result),AOP(left))){
5954     /* if left is same as result */
5955     for(;size--; offset++) {
5956       if(AOP_TYPE(right) == AOP_LIT){
5957         int t  = (lit >> (offset*8)) & 0x0FFL;
5958         if(t == 0x00L)
5959           continue;
5960         else
5961           if (IS_AOP_PREG(left)) {
5962             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5963             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5964             pic16_aopPut(AOP(result),"a",offset);
5965           } else {
5966             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5967             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5968             pic16_emitcode("xrl","%s,%s",
5969                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
5970                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5971           }
5972       } else {
5973         if (AOP_TYPE(left) == AOP_ACC)
5974           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5975         else {
5976           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5977           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5978 /*
5979           if (IS_AOP_PREG(left)) {
5980             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5981             pic16_aopPut(AOP(result),"a",offset);
5982           } else
5983             pic16_emitcode("xrl","%s,a",
5984                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5985 */
5986         }
5987       }
5988     }
5989   } else {
5990     // left & result in different registers
5991     if(AOP_TYPE(result) == AOP_CRY){
5992       // result = bit
5993       // if(size), result in bit
5994       // if(!size && ifx), conditional oper: if(left ^ right)
5995       symbol *tlbl = newiTempLabel(NULL);
5996       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5997       if(size)
5998         pic16_emitcode("setb","c");
5999       while(sizer--){
6000         if((AOP_TYPE(right) == AOP_LIT) &&
6001            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6002           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6003         } else {
6004           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6005           pic16_emitcode("xrl","a,%s",
6006                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6007         }
6008         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6009         offset++;
6010       }
6011       if(size){
6012         CLRC;
6013         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6014         pic16_outBitC(result);
6015       } else if(ifx)
6016         jmpTrueOrFalse(ifx, tlbl);
6017     } else for(;(size--);offset++){
6018       // normal case
6019       // result = left & right
6020       if(AOP_TYPE(right) == AOP_LIT){
6021         int t = (lit >> (offset*8)) & 0x0FFL;
6022         switch(t) { 
6023         case 0x00:
6024           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6025           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
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         case 0xff:
6032           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6033           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6034           pic16_emitcode("comf","%s,w",
6035                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6036           pic16_emitcode("movwf","%s",
6037                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6038           break;
6039         default:
6040           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6041           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6042           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6043           pic16_emitcode("movlw","0x%x",t);
6044           pic16_emitcode("xorwf","%s,w",
6045                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6046           pic16_emitcode("movwf","%s",
6047                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6048
6049         }
6050         continue;
6051       }
6052
6053       // faster than result <- left, anl result,right
6054       // and better if result is SFR
6055       if (AOP_TYPE(left) == AOP_ACC) {
6056         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6057         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6058       } else {
6059         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6060         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6061         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6062         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6063       }
6064       if ( AOP_TYPE(result) != AOP_ACC){
6065         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6066         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6067       }
6068     }
6069   }
6070
6071   release :
6072     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6073   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6074   pic16_freeAsmop(result,NULL,ic,TRUE);     
6075 }
6076
6077 /*-----------------------------------------------------------------*/
6078 /* genInline - write the inline code out                           */
6079 /*-----------------------------------------------------------------*/
6080 static void genInline (iCode *ic)
6081 {
6082     char *buffer, *bp, *bp1;
6083     
6084     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6085
6086     _G.inLine += (!options.asmpeep);
6087
6088     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6089     strcpy(buffer,IC_INLINE(ic));
6090
6091     /* emit each line as a code */
6092     while (*bp) {
6093         if (*bp == '\n') {
6094             *bp++ = '\0';
6095
6096             if(*bp1)
6097               pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6098             bp1 = bp;
6099         } else {
6100             if (*bp == ':') {
6101                 bp++;
6102                 *bp = '\0';
6103                 bp++;
6104                 pic16_emitcode(bp1,"");
6105                 bp1 = bp;
6106             } else
6107                 bp++;
6108         }
6109     }
6110     if ((bp1 != bp) && *bp1)
6111       pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6112
6113     Safe_free(buffer);
6114
6115     _G.inLine -= (!options.asmpeep);
6116 }
6117
6118 /*-----------------------------------------------------------------*/
6119 /* genRRC - rotate right with carry                                */
6120 /*-----------------------------------------------------------------*/
6121 static void genRRC (iCode *ic)
6122 {
6123   operand *left , *result ;
6124   int size, offset = 0, same;
6125
6126   /* rotate right with carry */
6127   left = IC_LEFT(ic);
6128   result=IC_RESULT(ic);
6129   pic16_aopOp (left,ic,FALSE);
6130   pic16_aopOp (result,ic,FALSE);
6131
6132   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6133
6134   same = pic16_sameRegs(AOP(result),AOP(left));
6135
6136   size = AOP_SIZE(result);    
6137
6138   /* get the lsb and put it into the carry */
6139   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6140
6141   offset = 0 ;
6142
6143   while(size--) {
6144
6145     if(same) {
6146       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6147     } else {
6148       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6149       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6150     }
6151
6152     offset++;
6153   }
6154
6155   pic16_freeAsmop(left,NULL,ic,TRUE);
6156   pic16_freeAsmop(result,NULL,ic,TRUE);
6157 }
6158
6159 /*-----------------------------------------------------------------*/
6160 /* genRLC - generate code for rotate left with carry               */
6161 /*-----------------------------------------------------------------*/
6162 static void genRLC (iCode *ic)
6163 {    
6164   operand *left , *result ;
6165   int size, offset = 0;
6166   int same;
6167
6168   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6169   /* rotate right with carry */
6170   left = IC_LEFT(ic);
6171   result=IC_RESULT(ic);
6172   pic16_aopOp (left,ic,FALSE);
6173   pic16_aopOp (result,ic,FALSE);
6174
6175   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6176
6177   same = pic16_sameRegs(AOP(result),AOP(left));
6178
6179   /* move it to the result */
6180   size = AOP_SIZE(result);    
6181
6182   /* get the msb and put it into the carry */
6183   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6184
6185   offset = 0 ;
6186
6187   while(size--) {
6188
6189     if(same) {
6190       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6191     } else {
6192       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6193       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6194     }
6195
6196     offset++;
6197   }
6198
6199
6200   pic16_freeAsmop(left,NULL,ic,TRUE);
6201   pic16_freeAsmop(result,NULL,ic,TRUE);
6202 }
6203
6204 /*-----------------------------------------------------------------*/
6205 /* genGetHbit - generates code get highest order bit               */
6206 /*-----------------------------------------------------------------*/
6207 static void genGetHbit (iCode *ic)
6208 {
6209     operand *left, *result;
6210     left = IC_LEFT(ic);
6211     result=IC_RESULT(ic);
6212     pic16_aopOp (left,ic,FALSE);
6213     pic16_aopOp (result,ic,FALSE);
6214
6215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6216     /* get the highest order byte into a */
6217     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6218     if(AOP_TYPE(result) == AOP_CRY){
6219         pic16_emitcode("rlc","a");
6220         pic16_outBitC(result);
6221     }
6222     else{
6223         pic16_emitcode("rl","a");
6224         pic16_emitcode("anl","a,#0x01");
6225         pic16_outAcc(result);
6226     }
6227
6228
6229     pic16_freeAsmop(left,NULL,ic,TRUE);
6230     pic16_freeAsmop(result,NULL,ic,TRUE);
6231 }
6232
6233 /*-----------------------------------------------------------------*/
6234 /* AccRol - rotate left accumulator by known count                 */
6235 /*-----------------------------------------------------------------*/
6236 static void AccRol (int shCount)
6237 {
6238     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6239     shCount &= 0x0007;              // shCount : 0..7
6240     switch(shCount){
6241         case 0 :
6242             break;
6243         case 1 :
6244             pic16_emitcode("rl","a");
6245             break;
6246         case 2 :
6247             pic16_emitcode("rl","a");
6248             pic16_emitcode("rl","a");
6249             break;
6250         case 3 :
6251             pic16_emitcode("swap","a");
6252             pic16_emitcode("rr","a");
6253             break;
6254         case 4 :
6255             pic16_emitcode("swap","a");
6256             break;
6257         case 5 :
6258             pic16_emitcode("swap","a");
6259             pic16_emitcode("rl","a");
6260             break;
6261         case 6 :
6262             pic16_emitcode("rr","a");
6263             pic16_emitcode("rr","a");
6264             break;
6265         case 7 :
6266             pic16_emitcode("rr","a");
6267             break;
6268     }
6269 }
6270
6271 /*-----------------------------------------------------------------*/
6272 /* AccLsh - left shift accumulator by known count                  */
6273 /*-----------------------------------------------------------------*/
6274 static void AccLsh (int shCount)
6275 {
6276     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6277     if(shCount != 0){
6278         if(shCount == 1)
6279             pic16_emitcode("add","a,acc");
6280         else 
6281             if(shCount == 2) {
6282             pic16_emitcode("add","a,acc");
6283             pic16_emitcode("add","a,acc");
6284         } else {
6285             /* rotate left accumulator */
6286             AccRol(shCount);
6287             /* and kill the lower order bits */
6288             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6289         }
6290     }
6291 }
6292
6293 /*-----------------------------------------------------------------*/
6294 /* AccRsh - right shift accumulator by known count                 */
6295 /*-----------------------------------------------------------------*/
6296 static void AccRsh (int shCount)
6297 {
6298     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6299     if(shCount != 0){
6300         if(shCount == 1){
6301             CLRC;
6302             pic16_emitcode("rrc","a");
6303         } else {
6304             /* rotate right accumulator */
6305             AccRol(8 - shCount);
6306             /* and kill the higher order bits */
6307             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6308         }
6309     }
6310 }
6311
6312 #if 0
6313 /*-----------------------------------------------------------------*/
6314 /* AccSRsh - signed right shift accumulator by known count                 */
6315 /*-----------------------------------------------------------------*/
6316 static void AccSRsh (int shCount)
6317 {
6318     symbol *tlbl ;
6319     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6320     if(shCount != 0){
6321         if(shCount == 1){
6322             pic16_emitcode("mov","c,acc.7");
6323             pic16_emitcode("rrc","a");
6324         } else if(shCount == 2){
6325             pic16_emitcode("mov","c,acc.7");
6326             pic16_emitcode("rrc","a");
6327             pic16_emitcode("mov","c,acc.7");
6328             pic16_emitcode("rrc","a");
6329         } else {
6330             tlbl = newiTempLabel(NULL);
6331             /* rotate right accumulator */
6332             AccRol(8 - shCount);
6333             /* and kill the higher order bits */
6334             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6335             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6336             pic16_emitcode("orl","a,#0x%02x",
6337                      (unsigned char)~SRMask[shCount]);
6338             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6339         }
6340     }
6341 }
6342 #endif
6343 /*-----------------------------------------------------------------*/
6344 /* shiftR1Left2Result - shift right one byte from left to result   */
6345 /*-----------------------------------------------------------------*/
6346 static void shiftR1Left2ResultSigned (operand *left, int offl,
6347                                 operand *result, int offr,
6348                                 int shCount)
6349 {
6350   int same;
6351
6352   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6353
6354   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6355
6356   switch(shCount) {
6357   case 1:
6358     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6359     if(same) 
6360       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6361     else {
6362       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6363       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6364     }
6365
6366     break;
6367   case 2:
6368
6369     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6370     if(same) 
6371       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6372     else {
6373       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6374       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6375     }
6376     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6377     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6378
6379     break;
6380
6381   case 3:
6382     if(same)
6383       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6384     else {
6385       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6386       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6387     }
6388
6389     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6390     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6391     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6392
6393     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6394     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6395
6396     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6397     break;
6398
6399   case 4:
6400     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6401     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6402     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6403     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6404     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6405     break;
6406   case 5:
6407     if(same) {
6408       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6409     } else {
6410       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6411       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6412     }
6413     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6414     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6415     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6416     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6417     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6418     break;
6419
6420   case 6:
6421     if(same) {
6422       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6423       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6424       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6425       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6426       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6427       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6428     } else {
6429       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6430       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6431       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6432       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6433       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6434     }
6435     break;
6436
6437   case 7:
6438     if(same) {
6439       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6440       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6441       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6442       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6443     } else {
6444       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6445       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6446       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6447     }
6448
6449   default:
6450     break;
6451   }
6452 }
6453
6454 /*-----------------------------------------------------------------*/
6455 /* shiftR1Left2Result - shift right one byte from left to result   */
6456 /*-----------------------------------------------------------------*/
6457 static void shiftR1Left2Result (operand *left, int offl,
6458                                 operand *result, int offr,
6459                                 int shCount, int sign)
6460 {
6461   int same;
6462
6463   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6464
6465   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6466
6467   /* Copy the msb into the carry if signed. */
6468   if(sign) {
6469     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6470     return;
6471   }
6472
6473
6474
6475   switch(shCount) {
6476   case 1:
6477     emitCLRC;
6478     if(same) 
6479       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6480     else {
6481       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6482       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6483     }
6484     break;
6485   case 2:
6486     emitCLRC;
6487     if(same) {
6488       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6489     } else {
6490       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6491       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6492     }
6493     emitCLRC;
6494     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6495
6496     break;
6497   case 3:
6498     if(same)
6499       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6500     else {
6501       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6502       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6503     }
6504
6505     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6506     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6507     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6508     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6509     break;
6510       
6511   case 4:
6512     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6513     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6514     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6515     break;
6516
6517   case 5:
6518     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6519     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6520     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6521     emitCLRC;
6522     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6523
6524     break;
6525   case 6:
6526
6527     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6528     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6529     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6530     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6531     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6532     break;
6533
6534   case 7:
6535
6536     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6537     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6538     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6539
6540     break;
6541
6542   default:
6543     break;
6544   }
6545 }
6546
6547 /*-----------------------------------------------------------------*/
6548 /* shiftL1Left2Result - shift left one byte from left to result    */
6549 /*-----------------------------------------------------------------*/
6550 static void shiftL1Left2Result (operand *left, int offl,
6551                                 operand *result, int offr, int shCount)
6552 {
6553   int same;
6554
6555   //    char *l;
6556   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6557
6558   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6559   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6560     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6561     //    MOVA(l);
6562     /* shift left accumulator */
6563     //AccLsh(shCount); // don't comment out just yet...
6564   //    pic16_aopPut(AOP(result),"a",offr);
6565
6566   switch(shCount) {
6567   case 1:
6568     /* Shift left 1 bit position */
6569     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6570     if(same) {
6571       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6572     } else {
6573       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6574       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6575     }
6576     break;
6577   case 2:
6578     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6579     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6580     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6581     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6582     break;
6583   case 3:
6584     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6585     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6586     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6587     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6588     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6589     break;
6590   case 4:
6591     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6592     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6593     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6594     break;
6595   case 5:
6596     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6597     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6598     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6599     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6600     break;
6601   case 6:
6602     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6603     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6604     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6605     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6606     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6607     break;
6608   case 7:
6609     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6610     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6611     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6612     break;
6613
6614   default:
6615     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6616   }
6617
6618 }
6619
6620 /*-----------------------------------------------------------------*/
6621 /* movLeft2Result - move byte from left to result                  */
6622 /*-----------------------------------------------------------------*/
6623 static void movLeft2Result (operand *left, int offl,
6624                             operand *result, int offr)
6625 {
6626   char *l;
6627   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6629     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6630
6631     if (*l == '@' && (IS_AOP_PREG(result))) {
6632       pic16_emitcode("mov","a,%s",l);
6633       pic16_aopPut(AOP(result),"a",offr);
6634     } else {
6635       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6636       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6637     }
6638   }
6639 }
6640
6641 /*-----------------------------------------------------------------*/
6642 /* shiftL2Left2Result - shift left two bytes from left to result   */
6643 /*-----------------------------------------------------------------*/
6644 static void shiftL2Left2Result (operand *left, int offl,
6645                                 operand *result, int offr, int shCount)
6646 {
6647
6648
6649   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6650
6651   if(pic16_sameRegs(AOP(result), AOP(left))) {
6652     switch(shCount) {
6653     case 0:
6654       break;
6655     case 1:
6656     case 2:
6657     case 3:
6658
6659       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6660       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6661       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6662
6663       while(--shCount) {
6664         emitCLRC;
6665         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6666         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6667       }
6668
6669       break;
6670     case 4:
6671     case 5:
6672       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6673       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6674       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6675       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6676       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6677       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6678       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6679       if(shCount >=5) {
6680         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6681         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6682       }
6683       break;
6684     case 6:
6685       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6686       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6687       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6688       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6689       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6690       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6691       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6692       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6693       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6694       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6695       break;
6696     case 7:
6697       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6698       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6699       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6700       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6701       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6702     }
6703
6704   } else {
6705     switch(shCount) {
6706     case 0:
6707       break;
6708     case 1:
6709     case 2:
6710     case 3:
6711       /* note, use a mov/add for the shift since the mov has a
6712          chance of getting optimized out */
6713       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6714       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6715       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6716       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6717       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6718
6719       while(--shCount) {
6720         emitCLRC;
6721         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6722         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6723       }
6724       break;
6725
6726     case 4:
6727     case 5:
6728       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6729       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6730       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6731       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6732       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6733       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6734       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6735       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6736
6737
6738       if(shCount == 5) {
6739         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6740         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6741       }
6742       break;
6743     case 6:
6744       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6745       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6746       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6747       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6748
6749       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6750       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6751       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6752       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6753       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6754       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6755       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6756       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6757       break;
6758     case 7:
6759       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6760       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6761       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6762       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6763       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6764     }
6765   }
6766
6767 }
6768 /*-----------------------------------------------------------------*/
6769 /* shiftR2Left2Result - shift right two bytes from left to result  */
6770 /*-----------------------------------------------------------------*/
6771 static void shiftR2Left2Result (operand *left, int offl,
6772                                 operand *result, int offr,
6773                                 int shCount, int sign)
6774 {
6775   int same=0;
6776
6777   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6778   same = pic16_sameRegs(AOP(result), AOP(left));
6779
6780   if(same && ((offl + MSB16) == offr)){
6781     same=1;
6782     /* don't crash result[offr] */
6783     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6784     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6785   }
6786 /* else {
6787     movLeft2Result(left,offl, result, offr);
6788     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6789   }
6790 */
6791   /* a:x >> shCount (x = lsb(result))*/
6792 /*
6793   if(sign)
6794     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6795   else {
6796     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6797 */
6798   switch(shCount) {
6799   case 0:
6800     break;
6801   case 1:
6802   case 2:
6803   case 3:
6804     if(sign)
6805       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6806     else
6807       emitCLRC;
6808
6809     if(same) {
6810       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6811       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6812     } else {
6813       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6814       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6815       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6816       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6817     }
6818
6819     while(--shCount) {
6820       if(sign)
6821         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6822       else
6823         emitCLRC;
6824       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6825       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6826     }
6827     break;
6828   case 4:
6829   case 5:
6830     if(same) {
6831
6832       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
6833       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
6834       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6835
6836       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6837       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
6838       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6839       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6840     } else {
6841       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6842       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6843       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6844
6845       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6846       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6847       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6848       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6849       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6850     }
6851
6852     if(shCount >=5) {
6853       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6854       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6855     }
6856
6857     if(sign) {
6858       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
6859       pic16_emitpcode(POC_BTFSC, 
6860                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6861       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6862     }
6863
6864     break;
6865
6866   case 6:
6867     if(same) {
6868
6869       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6870       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6871
6872       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6873       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6874       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6875       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6876       if(sign) {
6877         pic16_emitpcode(POC_BTFSC, 
6878                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6879         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6880       }
6881       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6882       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
6883       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6884       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6885     } else {
6886       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6887       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6888       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6889       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6890       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6891       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6892       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
6893       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6894       if(sign) {
6895         pic16_emitpcode(POC_BTFSC, 
6896                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6897         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6898       }
6899       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6900       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6901
6902         
6903     }
6904
6905     break;
6906   case 7:
6907     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6908     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6909     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6910     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
6911     if(sign) {
6912       emitSKPNC;
6913       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
6914     } else 
6915       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6916   }
6917 }
6918
6919
6920 /*-----------------------------------------------------------------*/
6921 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6922 /*-----------------------------------------------------------------*/
6923 static void shiftLLeftOrResult (operand *left, int offl,
6924                                 operand *result, int offr, int shCount)
6925 {
6926     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6927     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6928     /* shift left accumulator */
6929     AccLsh(shCount);
6930     /* or with result */
6931     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6932     /* back to result */
6933     pic16_aopPut(AOP(result),"a",offr);
6934 }
6935
6936 /*-----------------------------------------------------------------*/
6937 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6938 /*-----------------------------------------------------------------*/
6939 static void shiftRLeftOrResult (operand *left, int offl,
6940                                 operand *result, int offr, int shCount)
6941 {
6942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6943     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6944     /* shift right accumulator */
6945     AccRsh(shCount);
6946     /* or with result */
6947     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6948     /* back to result */
6949     pic16_aopPut(AOP(result),"a",offr);
6950 }
6951
6952 /*-----------------------------------------------------------------*/
6953 /* genlshOne - left shift a one byte quantity by known count       */
6954 /*-----------------------------------------------------------------*/
6955 static void genlshOne (operand *result, operand *left, int shCount)
6956 {       
6957     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6958     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6959 }
6960
6961 /*-----------------------------------------------------------------*/
6962 /* genlshTwo - left shift two bytes by known amount != 0           */
6963 /*-----------------------------------------------------------------*/
6964 static void genlshTwo (operand *result,operand *left, int shCount)
6965 {
6966     int size;
6967     
6968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6969     size = pic16_getDataSize(result);
6970
6971     /* if shCount >= 8 */
6972     if (shCount >= 8) {
6973         shCount -= 8 ;
6974
6975         if (size > 1){
6976             if (shCount)
6977                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6978             else 
6979                 movLeft2Result(left, LSB, result, MSB16);
6980         }
6981         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
6982     }
6983
6984     /*  1 <= shCount <= 7 */
6985     else {  
6986         if(size == 1)
6987             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6988         else 
6989             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6990     }
6991 }
6992
6993 /*-----------------------------------------------------------------*/
6994 /* shiftLLong - shift left one long from left to result            */
6995 /* offl = LSB or MSB16                                             */
6996 /*-----------------------------------------------------------------*/
6997 static void shiftLLong (operand *left, operand *result, int offr )
6998 {
6999     char *l;
7000     int size = AOP_SIZE(result);
7001
7002     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7003     if(size >= LSB+offr){
7004         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7005         MOVA(l);
7006         pic16_emitcode("add","a,acc");
7007         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7008             size >= MSB16+offr && offr != LSB )
7009             pic16_emitcode("xch","a,%s",
7010                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7011         else        
7012             pic16_aopPut(AOP(result),"a",LSB+offr);
7013     }
7014
7015     if(size >= MSB16+offr){
7016         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7017             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7018             MOVA(l);
7019         }
7020         pic16_emitcode("rlc","a");
7021         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7022             size >= MSB24+offr && offr != LSB)
7023             pic16_emitcode("xch","a,%s",
7024                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7025         else        
7026             pic16_aopPut(AOP(result),"a",MSB16+offr);
7027     }
7028
7029     if(size >= MSB24+offr){
7030         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7031             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7032             MOVA(l);
7033         }
7034         pic16_emitcode("rlc","a");
7035         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7036             size >= MSB32+offr && offr != LSB )
7037             pic16_emitcode("xch","a,%s",
7038                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7039         else        
7040             pic16_aopPut(AOP(result),"a",MSB24+offr);
7041     }
7042
7043     if(size > MSB32+offr){
7044         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7045             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7046             MOVA(l);    
7047         }
7048         pic16_emitcode("rlc","a");
7049         pic16_aopPut(AOP(result),"a",MSB32+offr);
7050     }
7051     if(offr != LSB)
7052         pic16_aopPut(AOP(result),zero,LSB);       
7053 }
7054
7055 /*-----------------------------------------------------------------*/
7056 /* genlshFour - shift four byte by a known amount != 0             */
7057 /*-----------------------------------------------------------------*/
7058 static void genlshFour (operand *result, operand *left, int shCount)
7059 {
7060     int size;
7061
7062     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7063     size = AOP_SIZE(result);
7064
7065     /* if shifting more that 3 bytes */
7066     if (shCount >= 24 ) {
7067         shCount -= 24;
7068         if (shCount)
7069             /* lowest order of left goes to the highest
7070             order of the destination */
7071             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7072         else
7073             movLeft2Result(left, LSB, result, MSB32);
7074         pic16_aopPut(AOP(result),zero,LSB);
7075         pic16_aopPut(AOP(result),zero,MSB16);
7076         pic16_aopPut(AOP(result),zero,MSB32);
7077         return;
7078     }
7079
7080     /* more than two bytes */
7081     else if ( shCount >= 16 ) {
7082         /* lower order two bytes goes to higher order two bytes */
7083         shCount -= 16;
7084         /* if some more remaining */
7085         if (shCount)
7086             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7087         else {
7088             movLeft2Result(left, MSB16, result, MSB32);
7089             movLeft2Result(left, LSB, result, MSB24);
7090         }
7091         pic16_aopPut(AOP(result),zero,MSB16);
7092         pic16_aopPut(AOP(result),zero,LSB);
7093         return;
7094     }    
7095
7096     /* if more than 1 byte */
7097     else if ( shCount >= 8 ) {
7098         /* lower order three bytes goes to higher order  three bytes */
7099         shCount -= 8;
7100         if(size == 2){
7101             if(shCount)
7102                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7103             else
7104                 movLeft2Result(left, LSB, result, MSB16);
7105         }
7106         else{   /* size = 4 */
7107             if(shCount == 0){
7108                 movLeft2Result(left, MSB24, result, MSB32);
7109                 movLeft2Result(left, MSB16, result, MSB24);
7110                 movLeft2Result(left, LSB, result, MSB16);
7111                 pic16_aopPut(AOP(result),zero,LSB);
7112             }
7113             else if(shCount == 1)
7114                 shiftLLong(left, result, MSB16);
7115             else{
7116                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7117                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7118                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7119                 pic16_aopPut(AOP(result),zero,LSB);
7120             }
7121         }
7122     }
7123
7124     /* 1 <= shCount <= 7 */
7125     else if(shCount <= 2){
7126         shiftLLong(left, result, LSB);
7127         if(shCount == 2)
7128             shiftLLong(result, result, LSB);
7129     }
7130     /* 3 <= shCount <= 7, optimize */
7131     else{
7132         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7133         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7134         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7135     }
7136 }
7137
7138 /*-----------------------------------------------------------------*/
7139 /* genLeftShiftLiteral - left shifting by known count              */
7140 /*-----------------------------------------------------------------*/
7141 static void genLeftShiftLiteral (operand *left,
7142                                  operand *right,
7143                                  operand *result,
7144                                  iCode *ic)
7145 {    
7146     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7147     int size;
7148
7149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7150     pic16_freeAsmop(right,NULL,ic,TRUE);
7151
7152     pic16_aopOp(left,ic,FALSE);
7153     pic16_aopOp(result,ic,FALSE);
7154
7155     size = getSize(operandType(result));
7156
7157 #if VIEW_SIZE
7158     pic16_emitcode("; shift left ","result %d, left %d",size,
7159              AOP_SIZE(left));
7160 #endif
7161
7162     /* I suppose that the left size >= result size */
7163     if(shCount == 0){
7164         while(size--){
7165             movLeft2Result(left, size, result, size);
7166         }
7167     }
7168
7169     else if(shCount >= (size * 8))
7170         while(size--)
7171             pic16_aopPut(AOP(result),zero,size);
7172     else{
7173         switch (size) {
7174             case 1:
7175                 genlshOne (result,left,shCount);
7176                 break;
7177
7178             case 2:
7179             case 3:
7180                 genlshTwo (result,left,shCount);
7181                 break;
7182
7183             case 4:
7184                 genlshFour (result,left,shCount);
7185                 break;
7186         }
7187     }
7188     pic16_freeAsmop(left,NULL,ic,TRUE);
7189     pic16_freeAsmop(result,NULL,ic,TRUE);
7190 }
7191
7192 /*-----------------------------------------------------------------*
7193  * genMultiAsm - repeat assembly instruction for size of register.
7194  * if endian == 1, then the high byte (i.e base address + size of 
7195  * register) is used first else the low byte is used first;
7196  *-----------------------------------------------------------------*/
7197 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7198 {
7199
7200   int offset = 0;
7201
7202   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7203
7204   if(!reg)
7205     return;
7206
7207   if(!endian) {
7208     endian = 1;
7209   } else {
7210     endian = -1;
7211     offset = size-1;
7212   }
7213
7214   while(size--) {
7215     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7216     offset += endian;
7217   }
7218
7219 }
7220 /*-----------------------------------------------------------------*/
7221 /* genLeftShift - generates code for left shifting                 */
7222 /*-----------------------------------------------------------------*/
7223 static void genLeftShift (iCode *ic)
7224 {
7225   operand *left,*right, *result;
7226   int size, offset;
7227   char *l;
7228   symbol *tlbl , *tlbl1;
7229   pCodeOp *pctemp;
7230
7231   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7232
7233   right = IC_RIGHT(ic);
7234   left  = IC_LEFT(ic);
7235   result = IC_RESULT(ic);
7236
7237   pic16_aopOp(right,ic,FALSE);
7238
7239   /* if the shift count is known then do it 
7240      as efficiently as possible */
7241   if (AOP_TYPE(right) == AOP_LIT) {
7242     genLeftShiftLiteral (left,right,result,ic);
7243     return ;
7244   }
7245
7246   /* shift count is unknown then we have to form 
7247      a loop get the loop count in B : Note: we take
7248      only the lower order byte since shifting
7249      more that 32 bits make no sense anyway, ( the
7250      largest size of an object can be only 32 bits ) */  
7251
7252     
7253   pic16_aopOp(left,ic,FALSE);
7254   pic16_aopOp(result,ic,FALSE);
7255
7256   /* now move the left to the result if they are not the
7257      same */
7258   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7259       AOP_SIZE(result) > 1) {
7260
7261     size = AOP_SIZE(result);
7262     offset=0;
7263     while (size--) {
7264       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7265       if (*l == '@' && (IS_AOP_PREG(result))) {
7266
7267         pic16_emitcode("mov","a,%s",l);
7268         pic16_aopPut(AOP(result),"a",offset);
7269       } else {
7270         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7271         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7272         //pic16_aopPut(AOP(result),l,offset);
7273       }
7274       offset++;
7275     }
7276   }
7277
7278   size = AOP_SIZE(result);
7279
7280   /* if it is only one byte then */
7281   if (size == 1) {
7282     if(optimized_for_speed) {
7283       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7284       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7285       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7286       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7287       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7288       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7289       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7290       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7291       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7292       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7293       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7294       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7295     } else {
7296
7297       tlbl = newiTempLabel(NULL);
7298       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7299         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7300         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7301       }
7302
7303       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7304       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7305       pic16_emitpLabel(tlbl->key);
7306       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7307       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7308       emitSKPC;
7309       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7310     }
7311     goto release ;
7312   }
7313     
7314   if (pic16_sameRegs(AOP(left),AOP(result))) {
7315
7316     tlbl = newiTempLabel(NULL);
7317     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7318     genMultiAsm(POC_RRCF, result, size,1);
7319     pic16_emitpLabel(tlbl->key);
7320     genMultiAsm(POC_RLCF, result, size,0);
7321     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7322     emitSKPC;
7323     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7324     goto release;
7325   }
7326
7327   //tlbl = newiTempLabel(NULL);
7328   //offset = 0 ;   
7329   //tlbl1 = newiTempLabel(NULL);
7330
7331   //reAdjustPreg(AOP(result));    
7332     
7333   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7334   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7335   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7336   //MOVA(l);
7337   //pic16_emitcode("add","a,acc");         
7338   //pic16_aopPut(AOP(result),"a",offset++);
7339   //while (--size) {
7340   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7341   //  MOVA(l);
7342   //  pic16_emitcode("rlc","a");         
7343   //  pic16_aopPut(AOP(result),"a",offset++);
7344   //}
7345   //reAdjustPreg(AOP(result));
7346
7347   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7348   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7349
7350
7351   tlbl = newiTempLabel(NULL);
7352   tlbl1= newiTempLabel(NULL);
7353
7354   size = AOP_SIZE(result);
7355   offset = 1;
7356
7357   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7358
7359   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7360
7361   /* offset should be 0, 1 or 3 */
7362   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7363   emitSKPNZ;
7364   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7365
7366   pic16_emitpcode(POC_MOVWF, pctemp);
7367
7368
7369   pic16_emitpLabel(tlbl->key);
7370
7371   emitCLRC;
7372   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7373   while(--size)
7374     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7375
7376   pic16_emitpcode(POC_DECFSZ,  pctemp);
7377   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7378   pic16_emitpLabel(tlbl1->key);
7379
7380   pic16_popReleaseTempReg(pctemp);
7381
7382
7383  release:
7384   pic16_freeAsmop (right,NULL,ic,TRUE);
7385   pic16_freeAsmop(left,NULL,ic,TRUE);
7386   pic16_freeAsmop(result,NULL,ic,TRUE);
7387 }
7388
7389 /*-----------------------------------------------------------------*/
7390 /* genrshOne - right shift a one byte quantity by known count      */
7391 /*-----------------------------------------------------------------*/
7392 static void genrshOne (operand *result, operand *left,
7393                        int shCount, int sign)
7394 {
7395     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7396     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* genrshTwo - right shift two bytes by known amount != 0          */
7401 /*-----------------------------------------------------------------*/
7402 static void genrshTwo (operand *result,operand *left,
7403                        int shCount, int sign)
7404 {
7405   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7406   /* if shCount >= 8 */
7407   if (shCount >= 8) {
7408     shCount -= 8 ;
7409     if (shCount)
7410       shiftR1Left2Result(left, MSB16, result, LSB,
7411                          shCount, sign);
7412     else
7413       movLeft2Result(left, MSB16, result, LSB);
7414
7415     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7416
7417     if(sign) {
7418       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7419       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7420     }
7421   }
7422
7423   /*  1 <= shCount <= 7 */
7424   else
7425     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7426 }
7427
7428 /*-----------------------------------------------------------------*/
7429 /* shiftRLong - shift right one long from left to result           */
7430 /* offl = LSB or MSB16                                             */
7431 /*-----------------------------------------------------------------*/
7432 static void shiftRLong (operand *left, int offl,
7433                         operand *result, int sign)
7434 {
7435     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7436     if(!sign)
7437         pic16_emitcode("clr","c");
7438     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7439     if(sign)
7440         pic16_emitcode("mov","c,acc.7");
7441     pic16_emitcode("rrc","a");
7442     pic16_aopPut(AOP(result),"a",MSB32-offl);
7443     if(offl == MSB16)
7444         /* add sign of "a" */
7445         pic16_addSign(result, MSB32, sign);
7446
7447     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7448     pic16_emitcode("rrc","a");
7449     pic16_aopPut(AOP(result),"a",MSB24-offl);
7450
7451     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7452     pic16_emitcode("rrc","a");
7453     pic16_aopPut(AOP(result),"a",MSB16-offl);
7454
7455     if(offl == LSB){
7456         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7457         pic16_emitcode("rrc","a");
7458         pic16_aopPut(AOP(result),"a",LSB);
7459     }
7460 }
7461
7462 /*-----------------------------------------------------------------*/
7463 /* genrshFour - shift four byte by a known amount != 0             */
7464 /*-----------------------------------------------------------------*/
7465 static void genrshFour (operand *result, operand *left,
7466                         int shCount, int sign)
7467 {
7468   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7469   /* if shifting more that 3 bytes */
7470   if(shCount >= 24 ) {
7471     shCount -= 24;
7472     if(shCount)
7473       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7474     else
7475       movLeft2Result(left, MSB32, result, LSB);
7476
7477     pic16_addSign(result, MSB16, sign);
7478   }
7479   else if(shCount >= 16){
7480     shCount -= 16;
7481     if(shCount)
7482       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7483     else{
7484       movLeft2Result(left, MSB24, result, LSB);
7485       movLeft2Result(left, MSB32, result, MSB16);
7486     }
7487     pic16_addSign(result, MSB24, sign);
7488   }
7489   else if(shCount >= 8){
7490     shCount -= 8;
7491     if(shCount == 1)
7492       shiftRLong(left, MSB16, result, sign);
7493     else if(shCount == 0){
7494       movLeft2Result(left, MSB16, result, LSB);
7495       movLeft2Result(left, MSB24, result, MSB16);
7496       movLeft2Result(left, MSB32, result, MSB24);
7497       pic16_addSign(result, MSB32, sign);
7498     }
7499     else{
7500       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7501       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7502       /* the last shift is signed */
7503       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7504       pic16_addSign(result, MSB32, sign);
7505     }
7506   }
7507   else{   /* 1 <= shCount <= 7 */
7508     if(shCount <= 2){
7509       shiftRLong(left, LSB, result, sign);
7510       if(shCount == 2)
7511         shiftRLong(result, LSB, result, sign);
7512     }
7513     else{
7514       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7515       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7516       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7517     }
7518   }
7519 }
7520
7521 /*-----------------------------------------------------------------*/
7522 /* genRightShiftLiteral - right shifting by known count            */
7523 /*-----------------------------------------------------------------*/
7524 static void genRightShiftLiteral (operand *left,
7525                                   operand *right,
7526                                   operand *result,
7527                                   iCode *ic,
7528                                   int sign)
7529 {    
7530   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7531   int lsize,res_size;
7532
7533   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7534   pic16_freeAsmop(right,NULL,ic,TRUE);
7535
7536   pic16_aopOp(left,ic,FALSE);
7537   pic16_aopOp(result,ic,FALSE);
7538
7539 #if VIEW_SIZE
7540   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7541                  AOP_SIZE(left));
7542 #endif
7543
7544   lsize = pic16_getDataSize(left);
7545   res_size = pic16_getDataSize(result);
7546   /* test the LEFT size !!! */
7547
7548   /* I suppose that the left size >= result size */
7549   if(shCount == 0){
7550     while(res_size--)
7551       movLeft2Result(left, lsize, result, res_size);
7552   }
7553
7554   else if(shCount >= (lsize * 8)){
7555
7556     if(res_size == 1) {
7557       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7558       if(sign) {
7559         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7560         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7561       }
7562     } else {
7563
7564       if(sign) {
7565         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7566         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7567         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7568         while(res_size--)
7569           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7570
7571       } else {
7572
7573         while(res_size--)
7574           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7575       }
7576     }
7577   } else {
7578
7579     switch (res_size) {
7580     case 1:
7581       genrshOne (result,left,shCount,sign);
7582       break;
7583
7584     case 2:
7585       genrshTwo (result,left,shCount,sign);
7586       break;
7587
7588     case 4:
7589       genrshFour (result,left,shCount,sign);
7590       break;
7591     default :
7592       break;
7593     }
7594
7595   }
7596
7597   pic16_freeAsmop(left,NULL,ic,TRUE);
7598   pic16_freeAsmop(result,NULL,ic,TRUE);
7599 }
7600
7601 /*-----------------------------------------------------------------*/
7602 /* genSignedRightShift - right shift of signed number              */
7603 /*-----------------------------------------------------------------*/
7604 static void genSignedRightShift (iCode *ic)
7605 {
7606   operand *right, *left, *result;
7607   int size, offset;
7608   //  char *l;
7609   symbol *tlbl, *tlbl1 ;
7610   pCodeOp *pctemp;
7611
7612   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7613
7614   /* we do it the hard way put the shift count in b
7615      and loop thru preserving the sign */
7616   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7617
7618   right = IC_RIGHT(ic);
7619   left  = IC_LEFT(ic);
7620   result = IC_RESULT(ic);
7621
7622   pic16_aopOp(right,ic,FALSE);  
7623   pic16_aopOp(left,ic,FALSE);
7624   pic16_aopOp(result,ic,FALSE);
7625
7626
7627   if ( AOP_TYPE(right) == AOP_LIT) {
7628     genRightShiftLiteral (left,right,result,ic,1);
7629     return ;
7630   }
7631   /* shift count is unknown then we have to form 
7632      a loop get the loop count in B : Note: we take
7633      only the lower order byte since shifting
7634      more that 32 bits make no sense anyway, ( the
7635      largest size of an object can be only 32 bits ) */  
7636
7637   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7638   //pic16_emitcode("inc","b");
7639   //pic16_freeAsmop (right,NULL,ic,TRUE);
7640   //pic16_aopOp(left,ic,FALSE);
7641   //pic16_aopOp(result,ic,FALSE);
7642
7643   /* now move the left to the result if they are not the
7644      same */
7645   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7646       AOP_SIZE(result) > 1) {
7647
7648     size = AOP_SIZE(result);
7649     offset=0;
7650     while (size--) { 
7651       /*
7652         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7653         if (*l == '@' && IS_AOP_PREG(result)) {
7654
7655         pic16_emitcode("mov","a,%s",l);
7656         pic16_aopPut(AOP(result),"a",offset);
7657         } else
7658         pic16_aopPut(AOP(result),l,offset);
7659       */
7660       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7661       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7662
7663       offset++;
7664     }
7665   }
7666
7667   /* mov the highest order bit to OVR */    
7668   tlbl = newiTempLabel(NULL);
7669   tlbl1= newiTempLabel(NULL);
7670
7671   size = AOP_SIZE(result);
7672   offset = size - 1;
7673
7674   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7675
7676   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7677
7678   /* offset should be 0, 1 or 3 */
7679   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7680   emitSKPNZ;
7681   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7682
7683   pic16_emitpcode(POC_MOVWF, pctemp);
7684
7685
7686   pic16_emitpLabel(tlbl->key);
7687
7688   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7689   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7690
7691   while(--size) {
7692     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7693   }
7694
7695   pic16_emitpcode(POC_DECFSZ,  pctemp);
7696   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7697   pic16_emitpLabel(tlbl1->key);
7698
7699   pic16_popReleaseTempReg(pctemp);
7700 #if 0
7701   size = AOP_SIZE(result);
7702   offset = size - 1;
7703   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7704   pic16_emitcode("rlc","a");
7705   pic16_emitcode("mov","ov,c");
7706   /* if it is only one byte then */
7707   if (size == 1) {
7708     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7709     MOVA(l);
7710     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7711     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7712     pic16_emitcode("mov","c,ov");
7713     pic16_emitcode("rrc","a");
7714     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7715     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7716     pic16_aopPut(AOP(result),"a",0);
7717     goto release ;
7718   }
7719
7720   reAdjustPreg(AOP(result));
7721   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7722   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7723   pic16_emitcode("mov","c,ov");
7724   while (size--) {
7725     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7726     MOVA(l);
7727     pic16_emitcode("rrc","a");         
7728     pic16_aopPut(AOP(result),"a",offset--);
7729   }
7730   reAdjustPreg(AOP(result));
7731   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7732   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7733
7734  release:
7735 #endif
7736
7737   pic16_freeAsmop(left,NULL,ic,TRUE);
7738   pic16_freeAsmop(result,NULL,ic,TRUE);
7739   pic16_freeAsmop(right,NULL,ic,TRUE);
7740 }
7741
7742 /*-----------------------------------------------------------------*/
7743 /* genRightShift - generate code for right shifting                */
7744 /*-----------------------------------------------------------------*/
7745 static void genRightShift (iCode *ic)
7746 {
7747     operand *right, *left, *result;
7748     sym_link *retype ;
7749     int size, offset;
7750     char *l;
7751     symbol *tlbl, *tlbl1 ;
7752
7753     /* if signed then we do it the hard way preserve the
7754     sign bit moving it inwards */
7755     retype = getSpec(operandType(IC_RESULT(ic)));
7756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7757
7758     if (!SPEC_USIGN(retype)) {
7759         genSignedRightShift (ic);
7760         return ;
7761     }
7762
7763     /* signed & unsigned types are treated the same : i.e. the
7764     signed is NOT propagated inwards : quoting from the
7765     ANSI - standard : "for E1 >> E2, is equivalent to division
7766     by 2**E2 if unsigned or if it has a non-negative value,
7767     otherwise the result is implementation defined ", MY definition
7768     is that the sign does not get propagated */
7769
7770     right = IC_RIGHT(ic);
7771     left  = IC_LEFT(ic);
7772     result = IC_RESULT(ic);
7773
7774     pic16_aopOp(right,ic,FALSE);
7775
7776     /* if the shift count is known then do it 
7777     as efficiently as possible */
7778     if (AOP_TYPE(right) == AOP_LIT) {
7779         genRightShiftLiteral (left,right,result,ic, 0);
7780         return ;
7781     }
7782
7783     /* shift count is unknown then we have to form 
7784     a loop get the loop count in B : Note: we take
7785     only the lower order byte since shifting
7786     more that 32 bits make no sense anyway, ( the
7787     largest size of an object can be only 32 bits ) */  
7788
7789     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7790     pic16_emitcode("inc","b");
7791     pic16_aopOp(left,ic,FALSE);
7792     pic16_aopOp(result,ic,FALSE);
7793
7794     /* now move the left to the result if they are not the
7795     same */
7796     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7797         AOP_SIZE(result) > 1) {
7798
7799         size = AOP_SIZE(result);
7800         offset=0;
7801         while (size--) {
7802             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7803             if (*l == '@' && IS_AOP_PREG(result)) {
7804
7805                 pic16_emitcode("mov","a,%s",l);
7806                 pic16_aopPut(AOP(result),"a",offset);
7807             } else
7808                 pic16_aopPut(AOP(result),l,offset);
7809             offset++;
7810         }
7811     }
7812
7813     tlbl = newiTempLabel(NULL);
7814     tlbl1= newiTempLabel(NULL);
7815     size = AOP_SIZE(result);
7816     offset = size - 1;
7817
7818     /* if it is only one byte then */
7819     if (size == 1) {
7820
7821       tlbl = newiTempLabel(NULL);
7822       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7823         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7824         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7825       }
7826
7827       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7828       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7829       pic16_emitpLabel(tlbl->key);
7830       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7831       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7832       emitSKPC;
7833       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7834
7835       goto release ;
7836     }
7837
7838     reAdjustPreg(AOP(result));
7839     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7840     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7841     CLRC;
7842     while (size--) {
7843         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7844         MOVA(l);
7845         pic16_emitcode("rrc","a");         
7846         pic16_aopPut(AOP(result),"a",offset--);
7847     }
7848     reAdjustPreg(AOP(result));
7849
7850     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7851     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7852
7853 release:
7854     pic16_freeAsmop(left,NULL,ic,TRUE);
7855     pic16_freeAsmop (right,NULL,ic,TRUE);
7856     pic16_freeAsmop(result,NULL,ic,TRUE);
7857 }
7858
7859 /*-----------------------------------------------------------------*/
7860 /* genUnpackBits - generates code for unpacking bits               */
7861 /*-----------------------------------------------------------------*/
7862 static void genUnpackBits (operand *result, char *rname, int ptype)
7863 {    
7864     int shCnt ;
7865     int rlen = 0 ;
7866     sym_link *etype;
7867     int offset = 0 ;
7868
7869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7870     etype = getSpec(operandType(result));
7871
7872     /* read the first byte  */
7873     switch (ptype) {
7874
7875     case POINTER:
7876     case IPOINTER:
7877         pic16_emitcode("mov","a,@%s",rname);
7878         break;
7879         
7880     case PPOINTER:
7881         pic16_emitcode("movx","a,@%s",rname);
7882         break;
7883         
7884     case FPOINTER:
7885         pic16_emitcode("movx","a,@dptr");
7886         break;
7887
7888     case CPOINTER:
7889         pic16_emitcode("clr","a");
7890         pic16_emitcode("movc","a","@a+dptr");
7891         break;
7892
7893     case GPOINTER:
7894         pic16_emitcode("lcall","__gptrget");
7895         break;
7896     }
7897
7898     /* if we have bitdisplacement then it fits   */
7899     /* into this byte completely or if length is */
7900     /* less than a byte                          */
7901     if ((shCnt = SPEC_BSTR(etype)) || 
7902         (SPEC_BLEN(etype) <= 8))  {
7903
7904         /* shift right acc */
7905         AccRsh(shCnt);
7906
7907         pic16_emitcode("anl","a,#0x%02x",
7908                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7909         pic16_aopPut(AOP(result),"a",offset);
7910         return ;
7911     }
7912
7913     /* bit field did not fit in a byte  */
7914     rlen = SPEC_BLEN(etype) - 8;
7915     pic16_aopPut(AOP(result),"a",offset++);
7916
7917     while (1)  {
7918
7919         switch (ptype) {
7920         case POINTER:
7921         case IPOINTER:
7922             pic16_emitcode("inc","%s",rname);
7923             pic16_emitcode("mov","a,@%s",rname);
7924             break;
7925             
7926         case PPOINTER:
7927             pic16_emitcode("inc","%s",rname);
7928             pic16_emitcode("movx","a,@%s",rname);
7929             break;
7930
7931         case FPOINTER:
7932             pic16_emitcode("inc","dptr");
7933             pic16_emitcode("movx","a,@dptr");
7934             break;
7935             
7936         case CPOINTER:
7937             pic16_emitcode("clr","a");
7938             pic16_emitcode("inc","dptr");
7939             pic16_emitcode("movc","a","@a+dptr");
7940             break;
7941             
7942         case GPOINTER:
7943             pic16_emitcode("inc","dptr");
7944             pic16_emitcode("lcall","__gptrget");
7945             break;
7946         }
7947
7948         rlen -= 8;            
7949         /* if we are done */
7950         if ( rlen <= 0 )
7951             break ;
7952         
7953         pic16_aopPut(AOP(result),"a",offset++);
7954                               
7955     }
7956     
7957     if (rlen) {
7958         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7959         pic16_aopPut(AOP(result),"a",offset);          
7960     }
7961     
7962     return ;
7963 }
7964
7965 #if 0
7966 /*-----------------------------------------------------------------*/
7967 /* genDataPointerGet - generates code when ptr offset is known     */
7968 /*-----------------------------------------------------------------*/
7969 static void genDataPointerGet (operand *left, 
7970                                operand *result, 
7971                                iCode *ic)
7972 {
7973   int size , offset = 0;
7974
7975
7976   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7977
7978
7979   /* optimization - most of the time, left and result are the same
7980    * address, but different types. for the pic code, we could omit
7981    * the following
7982    */
7983
7984   pic16_aopOp(result,ic,TRUE);
7985
7986   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7987
7988   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7989
7990   size = AOP_SIZE(result);
7991
7992   while (size--) {
7993     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7994     offset++;
7995   }
7996
7997   pic16_freeAsmop(left,NULL,ic,TRUE);
7998   pic16_freeAsmop(result,NULL,ic,TRUE);
7999 }
8000 #endif
8001 /*-----------------------------------------------------------------*/
8002 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8003 /*-----------------------------------------------------------------*/
8004 static void genNearPointerGet (operand *left, 
8005                                operand *result, 
8006                                iCode *ic)
8007 {
8008     asmop *aop = NULL;
8009     //regs *preg = NULL ;
8010     char *rname ;
8011     sym_link *rtype, *retype;
8012     sym_link *ltype = operandType(left);    
8013     //char buffer[80];
8014
8015     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8016
8017     rtype = operandType(result);
8018     retype= getSpec(rtype);
8019     
8020     pic16_aopOp(left,ic,FALSE);
8021     
8022     /* if left is rematerialisable and
8023        result is not bit variable type and
8024        the left is pointer to data space i.e
8025        lower 128 bytes of space */
8026     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8027         !IS_BITVAR(retype)         &&
8028         DCL_TYPE(ltype) == POINTER) {
8029       //genDataPointerGet (left,result,ic);
8030         return ;
8031     }
8032     
8033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8034
8035         /* if the value is already in a pointer register
8036        then don't need anything more */
8037     if (!AOP_INPREG(AOP(left))) {
8038         /* otherwise get a free pointer register */
8039     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8040 /*
8041         aop = newAsmop(0);
8042         preg = getFreePtr(ic,&aop,FALSE);
8043         pic16_emitcode("mov","%s,%s",
8044                 preg->name,
8045                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8046         rname = preg->name ;
8047 */
8048     rname ="BAD";
8049     } else
8050         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8051     
8052     pic16_aopOp (result,ic,FALSE);
8053     
8054       /* if bitfield then unpack the bits */
8055     if (IS_BITVAR(retype)) 
8056         genUnpackBits (result,rname,POINTER);
8057     else {
8058         /* we have can just get the values */
8059       int size = AOP_SIZE(result);
8060       int offset = 0 ;  
8061         
8062       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8063
8064       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8065       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8066       while(size--) {
8067         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8068         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8069         if(size)
8070           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8071       }
8072 /*
8073         while (size--) {
8074             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8075
8076                 pic16_emitcode("mov","a,@%s",rname);
8077                 pic16_aopPut(AOP(result),"a",offset);
8078             } else {
8079                 sprintf(buffer,"@%s",rname);
8080                 pic16_aopPut(AOP(result),buffer,offset);
8081             }
8082             offset++ ;
8083             if (size)
8084                 pic16_emitcode("inc","%s",rname);
8085         }
8086 */
8087     }
8088
8089     /* now some housekeeping stuff */
8090     if (aop) {
8091         /* we had to allocate for this iCode */
8092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8093         pic16_freeAsmop(NULL,aop,ic,TRUE);
8094     } else { 
8095         /* we did not allocate which means left
8096            already in a pointer register, then
8097            if size > 0 && this could be used again
8098            we have to point it back to where it 
8099            belongs */
8100     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8101         if (AOP_SIZE(result) > 1 &&
8102             !OP_SYMBOL(left)->remat &&
8103             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8104               ic->depth )) {
8105             int size = AOP_SIZE(result) - 1;
8106             while (size--)
8107                 pic16_emitcode("dec","%s",rname);
8108         }
8109     }
8110
8111     /* done */
8112     pic16_freeAsmop(left,NULL,ic,TRUE);
8113     pic16_freeAsmop(result,NULL,ic,TRUE);
8114      
8115 }
8116
8117 /*-----------------------------------------------------------------*/
8118 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8119 /*-----------------------------------------------------------------*/
8120 static void genPagedPointerGet (operand *left, 
8121                                operand *result, 
8122                                iCode *ic)
8123 {
8124     asmop *aop = NULL;
8125     regs *preg = NULL ;
8126     char *rname ;
8127     sym_link *rtype, *retype;    
8128
8129     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8130
8131     rtype = operandType(result);
8132     retype= getSpec(rtype);
8133     
8134     pic16_aopOp(left,ic,FALSE);
8135
8136   /* if the value is already in a pointer register
8137        then don't need anything more */
8138     if (!AOP_INPREG(AOP(left))) {
8139         /* otherwise get a free pointer register */
8140         aop = newAsmop(0);
8141         preg = getFreePtr(ic,&aop,FALSE);
8142         pic16_emitcode("mov","%s,%s",
8143                 preg->name,
8144                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8145         rname = preg->name ;
8146     } else
8147         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8148     
8149     pic16_freeAsmop(left,NULL,ic,TRUE);
8150     pic16_aopOp (result,ic,FALSE);
8151
8152     /* if bitfield then unpack the bits */
8153     if (IS_BITVAR(retype)) 
8154         genUnpackBits (result,rname,PPOINTER);
8155     else {
8156         /* we have can just get the values */
8157         int size = AOP_SIZE(result);
8158         int offset = 0 ;        
8159         
8160         while (size--) {
8161             
8162             pic16_emitcode("movx","a,@%s",rname);
8163             pic16_aopPut(AOP(result),"a",offset);
8164             
8165             offset++ ;
8166             
8167             if (size)
8168                 pic16_emitcode("inc","%s",rname);
8169         }
8170     }
8171
8172     /* now some housekeeping stuff */
8173     if (aop) {
8174         /* we had to allocate for this iCode */
8175         pic16_freeAsmop(NULL,aop,ic,TRUE);
8176     } else { 
8177         /* we did not allocate which means left
8178            already in a pointer register, then
8179            if size > 0 && this could be used again
8180            we have to point it back to where it 
8181            belongs */
8182         if (AOP_SIZE(result) > 1 &&
8183             !OP_SYMBOL(left)->remat &&
8184             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8185               ic->depth )) {
8186             int size = AOP_SIZE(result) - 1;
8187             while (size--)
8188                 pic16_emitcode("dec","%s",rname);
8189         }
8190     }
8191
8192     /* done */
8193     pic16_freeAsmop(result,NULL,ic,TRUE);
8194     
8195         
8196 }
8197
8198 /*-----------------------------------------------------------------*/
8199 /* genFarPointerGet - gget value from far space                    */
8200 /*-----------------------------------------------------------------*/
8201 static void genFarPointerGet (operand *left,
8202                               operand *result, iCode *ic)
8203 {
8204     int size, offset ;
8205     sym_link *retype = getSpec(operandType(result));
8206
8207     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8208
8209     pic16_aopOp(left,ic,FALSE);
8210
8211     /* if the operand is already in dptr 
8212     then we do nothing else we move the value to dptr */
8213     if (AOP_TYPE(left) != AOP_STR) {
8214         /* if this is remateriazable */
8215         if (AOP_TYPE(left) == AOP_IMMD)
8216             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8217         else { /* we need to get it byte by byte */
8218             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8219             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8220             if (options.model == MODEL_FLAT24)
8221             {
8222                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8223             }
8224         }
8225     }
8226     /* so dptr know contains the address */
8227     pic16_freeAsmop(left,NULL,ic,TRUE);
8228     pic16_aopOp(result,ic,FALSE);
8229
8230     /* if bit then unpack */
8231     if (IS_BITVAR(retype)) 
8232         genUnpackBits(result,"dptr",FPOINTER);
8233     else {
8234         size = AOP_SIZE(result);
8235         offset = 0 ;
8236
8237         while (size--) {
8238             pic16_emitcode("movx","a,@dptr");
8239             pic16_aopPut(AOP(result),"a",offset++);
8240             if (size)
8241                 pic16_emitcode("inc","dptr");
8242         }
8243     }
8244
8245     pic16_freeAsmop(result,NULL,ic,TRUE);
8246 }
8247 #if 0
8248 /*-----------------------------------------------------------------*/
8249 /* genCodePointerGet - get value from code space                  */
8250 /*-----------------------------------------------------------------*/
8251 static void genCodePointerGet (operand *left,
8252                                 operand *result, iCode *ic)
8253 {
8254     int size, offset ;
8255     sym_link *retype = getSpec(operandType(result));
8256
8257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8258
8259     pic16_aopOp(left,ic,FALSE);
8260
8261     /* if the operand is already in dptr 
8262     then we do nothing else we move the value to dptr */
8263     if (AOP_TYPE(left) != AOP_STR) {
8264         /* if this is remateriazable */
8265         if (AOP_TYPE(left) == AOP_IMMD)
8266             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8267         else { /* we need to get it byte by byte */
8268             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8269             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8270             if (options.model == MODEL_FLAT24)
8271             {
8272                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8273             }
8274         }
8275     }
8276     /* so dptr know contains the address */
8277     pic16_freeAsmop(left,NULL,ic,TRUE);
8278     pic16_aopOp(result,ic,FALSE);
8279
8280     /* if bit then unpack */
8281     if (IS_BITVAR(retype)) 
8282         genUnpackBits(result,"dptr",CPOINTER);
8283     else {
8284         size = AOP_SIZE(result);
8285         offset = 0 ;
8286
8287         while (size--) {
8288             pic16_emitcode("clr","a");
8289             pic16_emitcode("movc","a,@a+dptr");
8290             pic16_aopPut(AOP(result),"a",offset++);
8291             if (size)
8292                 pic16_emitcode("inc","dptr");
8293         }
8294     }
8295
8296     pic16_freeAsmop(result,NULL,ic,TRUE);
8297 }
8298 #endif
8299 /*-----------------------------------------------------------------*/
8300 /* genGenPointerGet - gget value from generic pointer space        */
8301 /*-----------------------------------------------------------------*/
8302 static void genGenPointerGet (operand *left,
8303                               operand *result, iCode *ic)
8304 {
8305   int size, offset ;
8306   sym_link *retype = getSpec(operandType(result));
8307
8308   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8309   pic16_aopOp(left,ic,FALSE);
8310   pic16_aopOp(result,ic,FALSE);
8311
8312
8313   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8314
8315   /* if the operand is already in dptr 
8316      then we do nothing else we move the value to dptr */
8317   //  if (AOP_TYPE(left) != AOP_STR) {
8318     /* if this is remateriazable */
8319     if (AOP_TYPE(left) == AOP_IMMD) {
8320       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8321       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8322     }
8323     else { /* we need to get it byte by byte */
8324
8325       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8326       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8327
8328       size = AOP_SIZE(result);
8329       offset = 0 ;
8330
8331       while(size--) {
8332         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8333         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8334         if(size)
8335           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8336       }
8337       goto release;
8338     }
8339     //}
8340   /* so dptr know contains the address */
8341
8342   /* if bit then unpack */
8343   //if (IS_BITVAR(retype)) 
8344   //  genUnpackBits(result,"dptr",GPOINTER);
8345
8346  release:
8347   pic16_freeAsmop(left,NULL,ic,TRUE);
8348   pic16_freeAsmop(result,NULL,ic,TRUE);
8349
8350 }
8351
8352 /*-----------------------------------------------------------------*/
8353 /* genConstPointerGet - get value from const generic pointer space */
8354 /*-----------------------------------------------------------------*/
8355 static void genConstPointerGet (operand *left,
8356                                 operand *result, iCode *ic)
8357 {
8358   //sym_link *retype = getSpec(operandType(result));
8359   symbol *albl = newiTempLabel(NULL);
8360   symbol *blbl = newiTempLabel(NULL);
8361   PIC_OPCODE poc;
8362
8363   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8364   pic16_aopOp(left,ic,FALSE);
8365   pic16_aopOp(result,ic,FALSE);
8366
8367
8368   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8369
8370   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8371
8372   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8373   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8374   pic16_emitpLabel(albl->key);
8375
8376   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8377     
8378   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8379   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8380   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8381   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8382
8383   pic16_emitpLabel(blbl->key);
8384
8385   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8386
8387
8388   pic16_freeAsmop(left,NULL,ic,TRUE);
8389   pic16_freeAsmop(result,NULL,ic,TRUE);
8390
8391 }
8392 /*-----------------------------------------------------------------*/
8393 /* genPointerGet - generate code for pointer get                   */
8394 /*-----------------------------------------------------------------*/
8395 static void genPointerGet (iCode *ic)
8396 {
8397     operand *left, *result ;
8398     sym_link *type, *etype;
8399     int p_type;
8400
8401     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8402
8403     left = IC_LEFT(ic);
8404     result = IC_RESULT(ic) ;
8405
8406     /* depending on the type of pointer we need to
8407     move it to the correct pointer register */
8408     type = operandType(left);
8409     etype = getSpec(type);
8410
8411     if (IS_PTR_CONST(type))
8412       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8413
8414     /* if left is of type of pointer then it is simple */
8415     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8416         p_type = DCL_TYPE(type);
8417     else {
8418         /* we have to go by the storage class */
8419         p_type = PTR_TYPE(SPEC_OCLS(etype));
8420
8421         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8422
8423         if (SPEC_OCLS(etype)->codesp ) {
8424           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8425           //p_type = CPOINTER ; 
8426         }
8427         else
8428             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8429               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8430                /*p_type = FPOINTER ;*/ 
8431             else
8432                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8433                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8434 /*                  p_type = PPOINTER; */
8435                 else
8436                     if (SPEC_OCLS(etype) == idata )
8437                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8438 /*                      p_type = IPOINTER; */
8439                     else
8440                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8441 /*                      p_type = POINTER ; */
8442     }
8443
8444     /* now that we have the pointer type we assign
8445     the pointer values */
8446     switch (p_type) {
8447
8448     case POINTER:       
8449     case IPOINTER:
8450         genNearPointerGet (left,result,ic);
8451         break;
8452
8453     case PPOINTER:
8454         genPagedPointerGet(left,result,ic);
8455         break;
8456
8457     case FPOINTER:
8458         genFarPointerGet (left,result,ic);
8459         break;
8460
8461     case CPOINTER:
8462         genConstPointerGet (left,result,ic);
8463         //pic16_emitcodePointerGet (left,result,ic);
8464         break;
8465
8466     case GPOINTER:
8467       if (IS_PTR_CONST(type))
8468         genConstPointerGet (left,result,ic);
8469       else
8470         genGenPointerGet (left,result,ic);
8471       break;
8472     }
8473
8474 }
8475
8476 /*-----------------------------------------------------------------*/
8477 /* genPackBits - generates code for packed bit storage             */
8478 /*-----------------------------------------------------------------*/
8479 static void genPackBits (sym_link    *etype ,
8480                          operand *right ,
8481                          char *rname, int p_type)
8482 {
8483     int shCount = 0 ;
8484     int offset = 0  ;
8485     int rLen = 0 ;
8486     int blen, bstr ;   
8487     char *l ;
8488
8489     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8490     blen = SPEC_BLEN(etype);
8491     bstr = SPEC_BSTR(etype);
8492
8493     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8494     MOVA(l);   
8495
8496     /* if the bit lenth is less than or    */
8497     /* it exactly fits a byte then         */
8498     if (SPEC_BLEN(etype) <= 8 )  {
8499         shCount = SPEC_BSTR(etype) ;
8500
8501         /* shift left acc */
8502         AccLsh(shCount);
8503
8504         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8505
8506
8507             switch (p_type) {
8508                 case POINTER:
8509                     pic16_emitcode ("mov","b,a");
8510                     pic16_emitcode("mov","a,@%s",rname);
8511                     break;
8512
8513                 case FPOINTER:
8514                     pic16_emitcode ("mov","b,a");
8515                     pic16_emitcode("movx","a,@dptr");
8516                     break;
8517
8518                 case GPOINTER:
8519                     pic16_emitcode ("push","b");
8520                     pic16_emitcode ("push","acc");
8521                     pic16_emitcode ("lcall","__gptrget");
8522                     pic16_emitcode ("pop","b");
8523                     break;
8524             }
8525
8526             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8527                       ((unsigned char)(0xFF << (blen+bstr)) | 
8528                        (unsigned char)(0xFF >> (8-bstr)) ) );
8529             pic16_emitcode ("orl","a,b");
8530             if (p_type == GPOINTER)
8531                 pic16_emitcode("pop","b");
8532         }
8533     }
8534
8535     switch (p_type) {
8536         case POINTER:
8537             pic16_emitcode("mov","@%s,a",rname);
8538             break;
8539
8540         case FPOINTER:
8541             pic16_emitcode("movx","@dptr,a");
8542             break;
8543
8544         case GPOINTER:
8545             DEBUGpic16_emitcode(";lcall","__gptrput");
8546             break;
8547     }
8548
8549     /* if we r done */
8550     if ( SPEC_BLEN(etype) <= 8 )
8551         return ;
8552
8553     pic16_emitcode("inc","%s",rname);
8554     rLen = SPEC_BLEN(etype) ;     
8555
8556     /* now generate for lengths greater than one byte */
8557     while (1) {
8558
8559         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8560
8561         rLen -= 8 ;
8562         if (rLen <= 0 )
8563             break ;
8564
8565         switch (p_type) {
8566             case POINTER:
8567                 if (*l == '@') {
8568                     MOVA(l);
8569                     pic16_emitcode("mov","@%s,a",rname);
8570                 } else
8571                     pic16_emitcode("mov","@%s,%s",rname,l);
8572                 break;
8573
8574             case FPOINTER:
8575                 MOVA(l);
8576                 pic16_emitcode("movx","@dptr,a");
8577                 break;
8578
8579             case GPOINTER:
8580                 MOVA(l);
8581                 DEBUGpic16_emitcode(";lcall","__gptrput");
8582                 break;  
8583         }   
8584         pic16_emitcode ("inc","%s",rname);
8585     }
8586
8587     MOVA(l);
8588
8589     /* last last was not complete */
8590     if (rLen)   {
8591         /* save the byte & read byte */
8592         switch (p_type) {
8593             case POINTER:
8594                 pic16_emitcode ("mov","b,a");
8595                 pic16_emitcode("mov","a,@%s",rname);
8596                 break;
8597
8598             case FPOINTER:
8599                 pic16_emitcode ("mov","b,a");
8600                 pic16_emitcode("movx","a,@dptr");
8601                 break;
8602
8603             case GPOINTER:
8604                 pic16_emitcode ("push","b");
8605                 pic16_emitcode ("push","acc");
8606                 pic16_emitcode ("lcall","__gptrget");
8607                 pic16_emitcode ("pop","b");
8608                 break;
8609         }
8610
8611         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8612         pic16_emitcode ("orl","a,b");
8613     }
8614
8615     if (p_type == GPOINTER)
8616         pic16_emitcode("pop","b");
8617
8618     switch (p_type) {
8619
8620     case POINTER:
8621         pic16_emitcode("mov","@%s,a",rname);
8622         break;
8623         
8624     case FPOINTER:
8625         pic16_emitcode("movx","@dptr,a");
8626         break;
8627         
8628     case GPOINTER:
8629         DEBUGpic16_emitcode(";lcall","__gptrput");
8630         break;                  
8631     }
8632 }
8633 /*-----------------------------------------------------------------*/
8634 /* genDataPointerSet - remat pointer to data space                 */
8635 /*-----------------------------------------------------------------*/
8636 static void genDataPointerSet(operand *right,
8637                               operand *result,
8638                               iCode *ic)
8639 {
8640     int size, offset = 0 ;
8641     char *l, buffer[256];
8642
8643     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8644     pic16_aopOp(right,ic,FALSE);
8645     
8646     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8647     size = AOP_SIZE(right);
8648 /*
8649     if ( AOP_TYPE(result) == AOP_PCODE) {
8650       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8651               AOP(result)->aopu.pcop->name,
8652               PCOI(AOP(result)->aopu.pcop)->offset);
8653     }
8654 */
8655
8656     // tsd, was l+1 - the underline `_' prefix was being stripped
8657     while (size--) {
8658       if (offset) {
8659         sprintf(buffer,"(%s + %d)",l,offset);
8660         fprintf(stderr,"oops  %s\n",buffer);
8661       } else
8662         sprintf(buffer,"%s",l);
8663
8664         if (AOP_TYPE(right) == AOP_LIT) {
8665           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8666           lit = lit >> (8*offset);
8667           if(lit&0xff) {
8668             pic16_emitcode("movlw","%d",lit);
8669             pic16_emitcode("movwf","%s",buffer);
8670
8671             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8672             //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8673             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8674
8675           } else {
8676             pic16_emitcode("clrf","%s",buffer);
8677             //pic16_emitpcode(POC_CLRF, popRegFromString(buffer));
8678             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8679           }
8680         }else {
8681           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8682           pic16_emitcode("movwf","%s",buffer);
8683
8684           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8685           //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8686           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8687
8688         }
8689
8690         offset++;
8691     }
8692
8693     pic16_freeAsmop(right,NULL,ic,TRUE);
8694     pic16_freeAsmop(result,NULL,ic,TRUE);
8695 }
8696
8697 /*-----------------------------------------------------------------*/
8698 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8699 /*-----------------------------------------------------------------*/
8700 static void genNearPointerSet (operand *right,
8701                                operand *result, 
8702                                iCode *ic)
8703 {
8704   asmop *aop = NULL;
8705   char *l;
8706   sym_link *retype;
8707   sym_link *ptype = operandType(result);
8708
8709     
8710   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8711   retype= getSpec(operandType(right));
8712
8713   pic16_aopOp(result,ic,FALSE);
8714
8715     
8716   /* if the result is rematerializable &
8717      in data space & not a bit variable */
8718   //if (AOP_TYPE(result) == AOP_IMMD &&
8719   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8720       DCL_TYPE(ptype) == POINTER   &&
8721       !IS_BITVAR(retype)) {
8722     genDataPointerSet (right,result,ic);
8723     pic16_freeAsmop(result,NULL,ic,TRUE);
8724     return;
8725   }
8726
8727   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8728   pic16_aopOp(right,ic,FALSE);
8729   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8730
8731   /* if the value is already in a pointer register
8732      then don't need anything more */
8733   if (!AOP_INPREG(AOP(result))) {
8734     /* otherwise get a free pointer register */
8735     //aop = newAsmop(0);
8736     //preg = getFreePtr(ic,&aop,FALSE);
8737     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8738     //pic16_emitcode("mov","%s,%s",
8739     //         preg->name,
8740     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8741     //rname = preg->name ;
8742     //pic16_emitcode("movwf","fsr0");
8743     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8744     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8745     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8746     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8747     goto release;
8748
8749   }// else
8750   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8751
8752
8753   /* if bitfield then unpack the bits */
8754   if (IS_BITVAR(retype)) {
8755     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8756            "The programmer is obviously confused");
8757     //genPackBits (retype,right,rname,POINTER);
8758     exit(1);
8759   }
8760   else {
8761     /* we have can just get the values */
8762     int size = AOP_SIZE(right);
8763     int offset = 0 ;    
8764
8765     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8766     while (size--) {
8767       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8768       if (*l == '@' ) {
8769         //MOVA(l);
8770         //pic16_emitcode("mov","@%s,a",rname);
8771         pic16_emitcode("movf","indf0,w ;1");
8772       } else {
8773
8774         if (AOP_TYPE(right) == AOP_LIT) {
8775           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8776           if(lit) {
8777             pic16_emitcode("movlw","%s",l);
8778             pic16_emitcode("movwf","indf0 ;2");
8779           } else 
8780             pic16_emitcode("clrf","indf0");
8781         }else {
8782           pic16_emitcode("movf","%s,w",l);
8783           pic16_emitcode("movwf","indf0 ;2");
8784         }
8785         //pic16_emitcode("mov","@%s,%s",rname,l);
8786       }
8787       if (size)
8788         pic16_emitcode("incf","fsr0,f ;3");
8789       //pic16_emitcode("inc","%s",rname);
8790       offset++;
8791     }
8792   }
8793
8794   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8795   /* now some housekeeping stuff */
8796   if (aop) {
8797     /* we had to allocate for this iCode */
8798     pic16_freeAsmop(NULL,aop,ic,TRUE);
8799   } else { 
8800     /* we did not allocate which means left
8801        already in a pointer register, then
8802        if size > 0 && this could be used again
8803        we have to point it back to where it 
8804        belongs */
8805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8806     if (AOP_SIZE(right) > 1 &&
8807         !OP_SYMBOL(result)->remat &&
8808         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8809           ic->depth )) {
8810       int size = AOP_SIZE(right) - 1;
8811       while (size--)
8812         pic16_emitcode("decf","fsr0,f");
8813       //pic16_emitcode("dec","%s",rname);
8814     }
8815   }
8816
8817   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8818   /* done */
8819  release:
8820   pic16_freeAsmop(right,NULL,ic,TRUE);
8821   pic16_freeAsmop(result,NULL,ic,TRUE);
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
8826 /*-----------------------------------------------------------------*/
8827 static void genPagedPointerSet (operand *right,
8828                                operand *result, 
8829                                iCode *ic)
8830 {
8831     asmop *aop = NULL;
8832     regs *preg = NULL ;
8833     char *rname , *l;
8834     sym_link *retype;
8835        
8836     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8837
8838     retype= getSpec(operandType(right));
8839     
8840     pic16_aopOp(result,ic,FALSE);
8841     
8842     /* if the value is already in a pointer register
8843        then don't need anything more */
8844     if (!AOP_INPREG(AOP(result))) {
8845         /* otherwise get a free pointer register */
8846         aop = newAsmop(0);
8847         preg = getFreePtr(ic,&aop,FALSE);
8848         pic16_emitcode("mov","%s,%s",
8849                 preg->name,
8850                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
8851         rname = preg->name ;
8852     } else
8853         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8854     
8855     pic16_freeAsmop(result,NULL,ic,TRUE);
8856     pic16_aopOp (right,ic,FALSE);
8857
8858     /* if bitfield then unpack the bits */
8859     if (IS_BITVAR(retype)) 
8860         genPackBits (retype,right,rname,PPOINTER);
8861     else {
8862         /* we have can just get the values */
8863         int size = AOP_SIZE(right);
8864         int offset = 0 ;        
8865         
8866         while (size--) {
8867             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8868             
8869             MOVA(l);
8870             pic16_emitcode("movx","@%s,a",rname);
8871
8872             if (size)
8873                 pic16_emitcode("inc","%s",rname);
8874
8875             offset++;
8876         }
8877     }
8878     
8879     /* now some housekeeping stuff */
8880     if (aop) {
8881         /* we had to allocate for this iCode */
8882         pic16_freeAsmop(NULL,aop,ic,TRUE);
8883     } else { 
8884         /* we did not allocate which means left
8885            already in a pointer register, then
8886            if size > 0 && this could be used again
8887            we have to point it back to where it 
8888            belongs */
8889         if (AOP_SIZE(right) > 1 &&
8890             !OP_SYMBOL(result)->remat &&
8891             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8892               ic->depth )) {
8893             int size = AOP_SIZE(right) - 1;
8894             while (size--)
8895                 pic16_emitcode("dec","%s",rname);
8896         }
8897     }
8898
8899     /* done */
8900     pic16_freeAsmop(right,NULL,ic,TRUE);
8901     
8902         
8903 }
8904
8905 /*-----------------------------------------------------------------*/
8906 /* genFarPointerSet - set value from far space                     */
8907 /*-----------------------------------------------------------------*/
8908 static void genFarPointerSet (operand *right,
8909                               operand *result, iCode *ic)
8910 {
8911     int size, offset ;
8912     sym_link *retype = getSpec(operandType(right));
8913
8914     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8915     pic16_aopOp(result,ic,FALSE);
8916
8917     /* if the operand is already in dptr 
8918     then we do nothing else we move the value to dptr */
8919     if (AOP_TYPE(result) != AOP_STR) {
8920         /* if this is remateriazable */
8921         if (AOP_TYPE(result) == AOP_IMMD)
8922             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8923         else { /* we need to get it byte by byte */
8924             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
8925             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
8926             if (options.model == MODEL_FLAT24)
8927             {
8928                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
8929             }
8930         }
8931     }
8932     /* so dptr know contains the address */
8933     pic16_freeAsmop(result,NULL,ic,TRUE);
8934     pic16_aopOp(right,ic,FALSE);
8935
8936     /* if bit then unpack */
8937     if (IS_BITVAR(retype)) 
8938         genPackBits(retype,right,"dptr",FPOINTER);
8939     else {
8940         size = AOP_SIZE(right);
8941         offset = 0 ;
8942
8943         while (size--) {
8944             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8945             MOVA(l);
8946             pic16_emitcode("movx","@dptr,a");
8947             if (size)
8948                 pic16_emitcode("inc","dptr");
8949         }
8950     }
8951
8952     pic16_freeAsmop(right,NULL,ic,TRUE);
8953 }
8954
8955 /*-----------------------------------------------------------------*/
8956 /* genGenPointerSet - set value from generic pointer space         */
8957 /*-----------------------------------------------------------------*/
8958 static void genGenPointerSet (operand *right,
8959                               operand *result, iCode *ic)
8960 {
8961   int size, offset ;
8962   sym_link *retype = getSpec(operandType(right));
8963
8964   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8965
8966   pic16_aopOp(result,ic,FALSE);
8967   pic16_aopOp(right,ic,FALSE);
8968   size = AOP_SIZE(right);
8969
8970   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8971
8972   /* if the operand is already in dptr 
8973      then we do nothing else we move the value to dptr */
8974   if (AOP_TYPE(result) != AOP_STR) {
8975     /* if this is remateriazable */
8976     if (AOP_TYPE(result) == AOP_IMMD) {
8977       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8978       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8979     }
8980     else { /* we need to get it byte by byte */
8981       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8982       size = AOP_SIZE(right);
8983       offset = 0 ;
8984
8985       /* hack hack! see if this the FSR. If so don't load W */
8986       if(AOP_TYPE(right) != AOP_ACC) {
8987
8988
8989         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
8990         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8991
8992         if(AOP_SIZE(result) > 1) {
8993           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
8994           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
8995           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
8996
8997         }
8998
8999         //if(size==2)
9000         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9001         //if(size==4) {
9002         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9003         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9004         //}
9005
9006         while(size--) {
9007           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9008           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9009           
9010           if(size)
9011             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9012         }
9013
9014
9015         goto release;
9016       } 
9017
9018       if(aopIdx(AOP(result),0) != 4) {
9019
9020         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9021         goto release;
9022       }
9023
9024       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9025       goto release;
9026
9027     }
9028   }
9029   /* so dptr know contains the address */
9030
9031
9032   /* if bit then unpack */
9033   if (IS_BITVAR(retype)) 
9034     genPackBits(retype,right,"dptr",GPOINTER);
9035   else {
9036     size = AOP_SIZE(right);
9037     offset = 0 ;
9038
9039   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9040
9041     while (size--) {
9042
9043       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9044       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9045
9046       if (AOP_TYPE(right) == AOP_LIT) 
9047         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9048       else
9049         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9050
9051       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9052
9053       offset++;
9054     }
9055   }
9056
9057  release:
9058   pic16_freeAsmop(right,NULL,ic,TRUE);
9059   pic16_freeAsmop(result,NULL,ic,TRUE);
9060 }
9061
9062 /*-----------------------------------------------------------------*/
9063 /* genPointerSet - stores the value into a pointer location        */
9064 /*-----------------------------------------------------------------*/
9065 static void genPointerSet (iCode *ic)
9066 {    
9067     operand *right, *result ;
9068     sym_link *type, *etype;
9069     int p_type;
9070
9071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9072
9073     right = IC_RIGHT(ic);
9074     result = IC_RESULT(ic) ;
9075
9076     /* depending on the type of pointer we need to
9077     move it to the correct pointer register */
9078     type = operandType(result);
9079     etype = getSpec(type);
9080     /* if left is of type of pointer then it is simple */
9081     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9082         p_type = DCL_TYPE(type);
9083     }
9084     else {
9085         /* we have to go by the storage class */
9086         p_type = PTR_TYPE(SPEC_OCLS(etype));
9087
9088 /*      if (SPEC_OCLS(etype)->codesp ) { */
9089 /*          p_type = CPOINTER ;  */
9090 /*      } */
9091 /*      else */
9092 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9093 /*              p_type = FPOINTER ; */
9094 /*          else */
9095 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9096 /*                  p_type = PPOINTER ; */
9097 /*              else */
9098 /*                  if (SPEC_OCLS(etype) == idata ) */
9099 /*                      p_type = IPOINTER ; */
9100 /*                  else */
9101 /*                      p_type = POINTER ; */
9102     }
9103
9104     /* now that we have the pointer type we assign
9105     the pointer values */
9106     switch (p_type) {
9107
9108     case POINTER:
9109     case IPOINTER:
9110         genNearPointerSet (right,result,ic);
9111         break;
9112
9113     case PPOINTER:
9114         genPagedPointerSet (right,result,ic);
9115         break;
9116
9117     case FPOINTER:
9118         genFarPointerSet (right,result,ic);
9119         break;
9120
9121     case GPOINTER:
9122         genGenPointerSet (right,result,ic);
9123         break;
9124
9125     default:
9126       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9127               "genPointerSet: illegal pointer type");
9128     }
9129 }
9130
9131 /*-----------------------------------------------------------------*/
9132 /* genIfx - generate code for Ifx statement                        */
9133 /*-----------------------------------------------------------------*/
9134 static void genIfx (iCode *ic, iCode *popIc)
9135 {
9136   operand *cond = IC_COND(ic);
9137   int isbit =0;
9138
9139   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9140
9141   pic16_aopOp(cond,ic,FALSE);
9142
9143   /* get the value into acc */
9144   if (AOP_TYPE(cond) != AOP_CRY)
9145     pic16_toBoolean(cond);
9146   else
9147     isbit = 1;
9148   /* the result is now in the accumulator */
9149   pic16_freeAsmop(cond,NULL,ic,TRUE);
9150
9151   /* if there was something to be popped then do it */
9152   if (popIc)
9153     genIpop(popIc);
9154
9155   /* if the condition is  a bit variable */
9156   if (isbit && IS_ITEMP(cond) && 
9157       SPIL_LOC(cond)) {
9158     genIfxJump(ic,SPIL_LOC(cond)->rname);
9159     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9160   }
9161   else {
9162     if (isbit && !IS_ITEMP(cond))
9163       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9164     else
9165       genIfxJump(ic,"a");
9166   }
9167   ic->generated = 1;
9168
9169 }
9170
9171 /*-----------------------------------------------------------------*/
9172 /* genAddrOf - generates code for address of                       */
9173 /*-----------------------------------------------------------------*/
9174 static void genAddrOf (iCode *ic)
9175 {
9176   operand *right, *result, *left;
9177   int size, offset ;
9178
9179   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9180
9181
9182   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9183
9184   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9185   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9186   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9187
9188   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9189
9190   size = AOP_SIZE(IC_RESULT(ic));
9191   offset = 0;
9192
9193   while (size--) {
9194     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9195     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9196     offset++;
9197   }
9198
9199   pic16_freeAsmop(left,NULL,ic,FALSE);
9200   pic16_freeAsmop(result,NULL,ic,TRUE);
9201
9202 }
9203
9204 #if 0
9205 /*-----------------------------------------------------------------*/
9206 /* genFarFarAssign - assignment when both are in far space         */
9207 /*-----------------------------------------------------------------*/
9208 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9209 {
9210     int size = AOP_SIZE(right);
9211     int offset = 0;
9212     char *l ;
9213     /* first push the right side on to the stack */
9214     while (size--) {
9215         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9216         MOVA(l);
9217         pic16_emitcode ("push","acc");
9218     }
9219     
9220     pic16_freeAsmop(right,NULL,ic,FALSE);
9221     /* now assign DPTR to result */
9222     pic16_aopOp(result,ic,FALSE);
9223     size = AOP_SIZE(result);
9224     while (size--) {
9225         pic16_emitcode ("pop","acc");
9226         pic16_aopPut(AOP(result),"a",--offset);
9227     }
9228     pic16_freeAsmop(result,NULL,ic,FALSE);
9229         
9230 }
9231 #endif
9232
9233 /*-----------------------------------------------------------------*/
9234 /* genAssign - generate code for assignment                        */
9235 /*-----------------------------------------------------------------*/
9236 static void genAssign (iCode *ic)
9237 {
9238   operand *result, *right;
9239   int size, offset,know_W;
9240   unsigned long lit = 0L;
9241
9242   result = IC_RESULT(ic);
9243   right  = IC_RIGHT(ic) ;
9244
9245   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9246
9247   /* if they are the same */
9248   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9249     return ;
9250
9251   pic16_aopOp(right,ic,FALSE);
9252   pic16_aopOp(result,ic,TRUE);
9253
9254   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9255
9256   /* if they are the same registers */
9257   if (pic16_sameRegs(AOP(right),AOP(result)))
9258     goto release;
9259
9260   /* if the result is a bit */
9261   if (AOP_TYPE(result) == AOP_CRY) {
9262
9263     /* if the right size is a literal then
9264        we know what the value is */
9265     if (AOP_TYPE(right) == AOP_LIT) {
9266           
9267       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9268                   pic16_popGet(AOP(result),0));
9269
9270       if (((int) operandLitValue(right))) 
9271         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9272                        AOP(result)->aopu.aop_dir,
9273                        AOP(result)->aopu.aop_dir);
9274       else
9275         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9276                        AOP(result)->aopu.aop_dir,
9277                        AOP(result)->aopu.aop_dir);
9278       goto release;
9279     }
9280
9281     /* the right is also a bit variable */
9282     if (AOP_TYPE(right) == AOP_CRY) {
9283       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9284       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9285       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9286
9287       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9288                      AOP(result)->aopu.aop_dir,
9289                      AOP(result)->aopu.aop_dir);
9290       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9291                      AOP(right)->aopu.aop_dir,
9292                      AOP(right)->aopu.aop_dir);
9293       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9294                      AOP(result)->aopu.aop_dir,
9295                      AOP(result)->aopu.aop_dir);
9296       goto release ;
9297     }
9298
9299     /* we need to or */
9300     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9301     pic16_toBoolean(right);
9302     emitSKPZ;
9303     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9304     //pic16_aopPut(AOP(result),"a",0);
9305     goto release ;
9306   }
9307
9308   /* bit variables done */
9309   /* general case */
9310   size = AOP_SIZE(result);
9311   offset = 0 ;
9312   if(AOP_TYPE(right) == AOP_LIT)
9313     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9314
9315   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9316   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9317     if(aopIdx(AOP(result),0) == 4) {
9318   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9319       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9320       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9321       goto release;
9322     } else
9323       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9324   }
9325
9326   know_W=-1;
9327   while (size--) {
9328   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9329     if(AOP_TYPE(right) == AOP_LIT) {
9330       if(lit&0xff) {
9331         if(know_W != (lit&0xff))
9332           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9333         know_W = lit&0xff;
9334         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9335       } else
9336         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9337
9338       lit >>= 8;
9339
9340     } else if (AOP_TYPE(right) == AOP_CRY) {
9341       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9342       if(offset == 0) {
9343         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9344         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9345       }
9346     } else {
9347   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9348       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9349       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9350     }
9351             
9352     offset++;
9353   }
9354
9355     
9356  release:
9357   pic16_freeAsmop (right,NULL,ic,FALSE);
9358   pic16_freeAsmop (result,NULL,ic,TRUE);
9359 }   
9360
9361 /*-----------------------------------------------------------------*/
9362 /* genJumpTab - genrates code for jump table                       */
9363 /*-----------------------------------------------------------------*/
9364 static void genJumpTab (iCode *ic)
9365 {
9366     symbol *jtab;
9367     char *l;
9368
9369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9370
9371     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9372     /* get the condition into accumulator */
9373     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9374     MOVA(l);
9375     /* multiply by three */
9376     pic16_emitcode("add","a,acc");
9377     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9378
9379     jtab = newiTempLabel(NULL);
9380     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9381     pic16_emitcode("jmp","@a+dptr");
9382     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9383
9384     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9385     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9386     emitSKPNC;
9387     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9388     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9389     pic16_emitpLabel(jtab->key);
9390
9391     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9392
9393     /* now generate the jump labels */
9394     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9395          jtab = setNextItem(IC_JTLABELS(ic))) {
9396         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9397         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9398         
9399     }
9400
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genMixedOperation - gen code for operators between mixed types  */
9405 /*-----------------------------------------------------------------*/
9406 /*
9407   TSD - Written for the PIC port - but this unfortunately is buggy.
9408   This routine is good in that it is able to efficiently promote 
9409   types to different (larger) sizes. Unfortunately, the temporary
9410   variables that are optimized out by this routine are sometimes
9411   used in other places. So until I know how to really parse the 
9412   iCode tree, I'm going to not be using this routine :(.
9413 */
9414 static int genMixedOperation (iCode *ic)
9415 {
9416 #if 0
9417   operand *result = IC_RESULT(ic);
9418   sym_link *ctype = operandType(IC_LEFT(ic));
9419   operand *right = IC_RIGHT(ic);
9420   int ret = 0;
9421   int big,small;
9422   int offset;
9423
9424   iCode *nextic;
9425   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9426
9427   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9428
9429   nextic = ic->next;
9430   if(!nextic)
9431     return 0;
9432
9433   nextright = IC_RIGHT(nextic);
9434   nextleft  = IC_LEFT(nextic);
9435   nextresult = IC_RESULT(nextic);
9436
9437   pic16_aopOp(right,ic,FALSE);
9438   pic16_aopOp(result,ic,FALSE);
9439   pic16_aopOp(nextright,  nextic, FALSE);
9440   pic16_aopOp(nextleft,   nextic, FALSE);
9441   pic16_aopOp(nextresult, nextic, FALSE);
9442
9443   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9444
9445     operand *t = right;
9446     right = nextright;
9447     nextright = t; 
9448
9449     pic16_emitcode(";remove right +","");
9450
9451   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9452 /*
9453     operand *t = right;
9454     right = nextleft;
9455     nextleft = t; 
9456 */
9457     pic16_emitcode(";remove left +","");
9458   } else
9459     return 0;
9460
9461   big = AOP_SIZE(nextleft);
9462   small = AOP_SIZE(nextright);
9463
9464   switch(nextic->op) {
9465
9466   case '+':
9467     pic16_emitcode(";optimize a +","");
9468     /* if unsigned or not an integral type */
9469     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9470       pic16_emitcode(";add a bit to something","");
9471     } else {
9472
9473       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9474
9475       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9476         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9477         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9478       } else
9479         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9480
9481       offset = 0;
9482       while(--big) {
9483
9484         offset++;
9485
9486         if(--small) {
9487           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9488             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9489             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9490           }
9491
9492           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9493           emitSKPNC;
9494           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9495                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9496                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9497           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9498           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9499
9500         } else {
9501           pic16_emitcode("rlf","known_zero,w");
9502
9503           /*
9504             if right is signed
9505               btfsc  right,7
9506                addlw ff
9507           */
9508           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9509             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9510             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9511           } else {
9512             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9513           }
9514         }
9515       }
9516       ret = 1;
9517     }
9518   }
9519   ret = 1;
9520
9521 release:
9522   pic16_freeAsmop(right,NULL,ic,TRUE);
9523   pic16_freeAsmop(result,NULL,ic,TRUE);
9524   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9525   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9526   if(ret)
9527     nextic->generated = 1;
9528
9529   return ret;
9530 #else
9531   return 0;
9532 #endif
9533 }
9534 /*-----------------------------------------------------------------*/
9535 /* genCast - gen code for casting                                  */
9536 /*-----------------------------------------------------------------*/
9537 static void genCast (iCode *ic)
9538 {
9539     operand *result = IC_RESULT(ic);
9540     sym_link *ctype = operandType(IC_LEFT(ic));
9541     sym_link *rtype = operandType(IC_RIGHT(ic));
9542     operand *right = IC_RIGHT(ic);
9543     int size, offset ;
9544
9545     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9546     /* if they are equivalent then do nothing */
9547     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9548         return ;
9549
9550     pic16_aopOp(right,ic,FALSE) ;
9551     pic16_aopOp(result,ic,FALSE);
9552
9553     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9554
9555     /* if the result is a bit */
9556     if (AOP_TYPE(result) == AOP_CRY) {
9557         /* if the right size is a literal then
9558         we know what the value is */
9559       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9560         if (AOP_TYPE(right) == AOP_LIT) {
9561
9562           pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9563                       pic16_popGet(AOP(result),0));
9564
9565             if (((int) operandLitValue(right))) 
9566               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9567                        AOP(result)->aopu.aop_dir,
9568                        AOP(result)->aopu.aop_dir);
9569             else
9570               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9571                        AOP(result)->aopu.aop_dir,
9572                        AOP(result)->aopu.aop_dir);
9573
9574             goto release;
9575         }
9576
9577         /* the right is also a bit variable */
9578         if (AOP_TYPE(right) == AOP_CRY) {
9579
9580           emitCLRC;
9581           pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9582
9583           pic16_emitcode("clrc","");
9584           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9585                    AOP(right)->aopu.aop_dir,
9586                    AOP(right)->aopu.aop_dir);
9587             pic16_aopPut(AOP(result),"c",0);
9588             goto release ;
9589         }
9590
9591         /* we need to or */
9592         if (AOP_TYPE(right) == AOP_REG) {
9593           pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9594           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9595           pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9596         }
9597         pic16_toBoolean(right);
9598         pic16_aopPut(AOP(result),"a",0);
9599         goto release ;
9600     }
9601
9602     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9603       int offset = 1;
9604       size = AOP_SIZE(result);
9605
9606       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9607
9608       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9609       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9610       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9611
9612       while (size--)
9613         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9614
9615       goto release;
9616     }
9617
9618     /* if they are the same size : or less */
9619     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9620
9621         /* if they are in the same place */
9622       if (pic16_sameRegs(AOP(right),AOP(result)))
9623         goto release;
9624
9625       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9626       if (IS_PTR_CONST(rtype))
9627         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9628       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9629         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9630
9631       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9632         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9633         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9634         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9635         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9636         if(AOP_SIZE(result) <2)
9637           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9638
9639       } else {
9640
9641         /* if they in different places then copy */
9642         size = AOP_SIZE(result);
9643         offset = 0 ;
9644         while (size--) {
9645           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9646           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9647
9648           //pic16_aopPut(AOP(result),
9649           // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9650           // offset);
9651
9652           offset++;
9653         }
9654       }
9655       goto release;
9656     }
9657
9658
9659     /* if the result is of type pointer */
9660     if (IS_PTR(ctype)) {
9661
9662         int p_type;
9663         sym_link *type = operandType(right);
9664         sym_link *etype = getSpec(type);
9665       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9666
9667         /* pointer to generic pointer */
9668         if (IS_GENPTR(ctype)) {
9669             char *l = zero;
9670             
9671             if (IS_PTR(type)) 
9672                 p_type = DCL_TYPE(type);
9673             else {
9674                 /* we have to go by the storage class */
9675                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9676
9677 /*              if (SPEC_OCLS(etype)->codesp )  */
9678 /*                  p_type = CPOINTER ;  */
9679 /*              else */
9680 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9681 /*                      p_type = FPOINTER ; */
9682 /*                  else */
9683 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9684 /*                          p_type = PPOINTER; */
9685 /*                      else */
9686 /*                          if (SPEC_OCLS(etype) == idata ) */
9687 /*                              p_type = IPOINTER ; */
9688 /*                          else */
9689 /*                              p_type = POINTER ; */
9690             }
9691                 
9692             /* the first two bytes are known */
9693       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9694             size = GPTRSIZE - 1; 
9695             offset = 0 ;
9696             while (size--) {
9697               if(offset < AOP_SIZE(right)) {
9698       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9699                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9700                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9701                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9702                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9703                 } else { 
9704                   pic16_aopPut(AOP(result),
9705                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9706                          offset);
9707                 }
9708               } else 
9709                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9710               offset++;
9711             }
9712             /* the last byte depending on type */
9713             switch (p_type) {
9714             case IPOINTER:
9715             case POINTER:
9716                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
9717                 break;
9718             case FPOINTER:
9719               pic16_emitcode(";BUG!? ","%d",__LINE__);
9720                 l = one;
9721                 break;
9722             case CPOINTER:
9723               pic16_emitcode(";BUG!? ","%d",__LINE__);
9724                 l = "#0x02";
9725                 break;                          
9726             case PPOINTER:
9727               pic16_emitcode(";BUG!? ","%d",__LINE__);
9728                 l = "#0x03";
9729                 break;
9730                 
9731             default:
9732                 /* this should never happen */
9733                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9734                        "got unknown pointer type");
9735                 exit(1);
9736             }
9737             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
9738             goto release ;
9739         }
9740         
9741         /* just copy the pointers */
9742         size = AOP_SIZE(result);
9743         offset = 0 ;
9744         while (size--) {
9745             pic16_aopPut(AOP(result),
9746                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9747                    offset);
9748             offset++;
9749         }
9750         goto release ;
9751     }
9752     
9753
9754
9755     /* so we now know that the size of destination is greater
9756     than the size of the source.
9757     Now, if the next iCode is an operator then we might be
9758     able to optimize the operation without performing a cast.
9759     */
9760     if(genMixedOperation(ic))
9761       goto release;
9762
9763     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9764     
9765     /* we move to result for the size of source */
9766     size = AOP_SIZE(right);
9767     offset = 0 ;
9768     while (size--) {
9769       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
9770       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
9771       offset++;
9772     }
9773
9774     /* now depending on the sign of the destination */
9775     size = AOP_SIZE(result) - AOP_SIZE(right);
9776     /* if unsigned or not an integral type */
9777     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9778       while (size--)
9779         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9780     } else {
9781       /* we need to extend the sign :{ */
9782
9783       if(size == 1) {
9784         /* Save one instruction of casting char to int */
9785         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9786         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9787         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
9788       } else {
9789         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9790
9791         if(offset)
9792           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9793         else
9794           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9795         
9796         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9797
9798         while (size--)
9799           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9800       }
9801     }
9802
9803 release:
9804     pic16_freeAsmop(right,NULL,ic,TRUE);
9805     pic16_freeAsmop(result,NULL,ic,TRUE);
9806
9807 }
9808
9809 /*-----------------------------------------------------------------*/
9810 /* genDjnz - generate decrement & jump if not zero instrucion      */
9811 /*-----------------------------------------------------------------*/
9812 static int genDjnz (iCode *ic, iCode *ifx)
9813 {
9814     symbol *lbl, *lbl1;
9815     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9816
9817     if (!ifx)
9818         return 0;
9819     
9820     /* if the if condition has a false label
9821        then we cannot save */
9822     if (IC_FALSE(ifx))
9823         return 0;
9824
9825     /* if the minus is not of the form 
9826        a = a - 1 */
9827     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9828         !IS_OP_LITERAL(IC_RIGHT(ic)))
9829         return 0;
9830
9831     if (operandLitValue(IC_RIGHT(ic)) != 1)
9832         return 0;
9833
9834     /* if the size of this greater than one then no
9835        saving */
9836     if (getSize(operandType(IC_RESULT(ic))) > 1)
9837         return 0;
9838
9839     /* otherwise we can save BIG */
9840     lbl = newiTempLabel(NULL);
9841     lbl1= newiTempLabel(NULL);
9842
9843     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9844     
9845     if (IS_AOP_PREG(IC_RESULT(ic))) {
9846         pic16_emitcode("dec","%s",
9847                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9848         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9849         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
9850     } else {    
9851
9852
9853       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9854       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9855
9856       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9857       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9858
9859     }
9860 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9861 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
9862 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9863 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
9864
9865     
9866     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9867     ifx->generated = 1;
9868     return 1;
9869 }
9870
9871 /*-----------------------------------------------------------------*/
9872 /* genReceive - generate code for a receive iCode                  */
9873 /*-----------------------------------------------------------------*/
9874 static void genReceive (iCode *ic)
9875 {    
9876   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9877
9878   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9879       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9880         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9881
9882     int size = getSize(operandType(IC_RESULT(ic)));
9883     int offset =  pic16_fReturnSizePic - size;
9884     while (size--) {
9885       pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9886                                     fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9887       offset++;
9888     }
9889     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9890     size = AOP_SIZE(IC_RESULT(ic));
9891     offset = 0;
9892     while (size--) {
9893       pic16_emitcode ("pop","acc");
9894       pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9895     }
9896         
9897   } else {
9898     _G.accInUse++;
9899     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9900     _G.accInUse--;
9901     assignResultValue(IC_RESULT(ic));   
9902   }
9903
9904   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9905 }
9906
9907 /*-----------------------------------------------------------------*/
9908 /* genpic16Code - generate code for pic16 based controllers        */
9909 /*-----------------------------------------------------------------*/
9910 /*
9911  * At this point, ralloc.c has gone through the iCode and attempted
9912  * to optimize in a way suitable for a PIC. Now we've got to generate
9913  * PIC instructions that correspond to the iCode.
9914  *
9915  * Once the instructions are generated, we'll pass through both the
9916  * peep hole optimizer and the pCode optimizer.
9917  *-----------------------------------------------------------------*/
9918
9919 void genpic16Code (iCode *lic)
9920 {
9921     iCode *ic;
9922     int cln = 0;
9923
9924     lineHead = lineCurr = NULL;
9925
9926     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
9927     pic16_addpBlock(pb);
9928
9929     /* if debug information required */
9930     if (options.debug && currFunc) { 
9931       if (currFunc) {
9932         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9933         _G.debugLine = 1;
9934         if (IS_STATIC(currFunc->etype)) {
9935           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9936           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
9937         } else {
9938           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9939           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
9940         }
9941         _G.debugLine = 0;
9942       }
9943     }
9944
9945
9946     for (ic = lic ; ic ; ic = ic->next ) {
9947
9948       DEBUGpic16_emitcode(";ic","");
9949         if ( cln != ic->lineno ) {
9950             if ( options.debug ) {
9951                 _G.debugLine = 1;
9952                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
9953                          FileBaseName(ic->filename),ic->lineno,
9954                          ic->level,ic->block);
9955                 _G.debugLine = 0;
9956             }
9957             /*
9958               pic16_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9959               pic16_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9960               printCLine(ic->filename, ic->lineno));
9961             */
9962             pic16_addpCode2pBlock(pb,
9963                             pic16_newpCodeCSource(ic->lineno, 
9964                                             ic->filename, 
9965                                             printCLine(ic->filename, ic->lineno)));
9966
9967             cln = ic->lineno ;
9968         }
9969         /* if the result is marked as
9970            spilt and rematerializable or code for
9971            this has already been generated then
9972            do nothing */
9973         if (resultRemat(ic) || ic->generated ) 
9974             continue ;
9975         
9976         /* depending on the operation */
9977         switch (ic->op) {
9978         case '!' :
9979             genNot(ic);
9980             break;
9981             
9982         case '~' :
9983             genCpl(ic);
9984             break;
9985             
9986         case UNARYMINUS:
9987             genUminus (ic);
9988             break;
9989             
9990         case IPUSH:
9991             genIpush (ic);
9992             break;
9993             
9994         case IPOP:
9995             /* IPOP happens only when trying to restore a 
9996                spilt live range, if there is an ifx statement
9997                following this pop then the if statement might
9998                be using some of the registers being popped which
9999                would destroy the contents of the register so
10000                we need to check for this condition and handle it */
10001             if (ic->next            && 
10002                 ic->next->op == IFX &&
10003                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10004                 genIfx (ic->next,ic);
10005             else
10006                 genIpop (ic);
10007             break; 
10008             
10009         case CALL:
10010             genCall (ic);
10011             break;
10012             
10013         case PCALL:
10014             genPcall (ic);
10015             break;
10016             
10017         case FUNCTION:
10018             genFunction (ic);
10019             break;
10020             
10021         case ENDFUNCTION:
10022             genEndFunction (ic);
10023             break;
10024             
10025         case RETURN:
10026             genRet (ic);
10027             break;
10028             
10029         case LABEL:
10030             genLabel (ic);
10031             break;
10032             
10033         case GOTO:
10034             genGoto (ic);
10035             break;
10036             
10037         case '+' :
10038             pic16_genPlus (ic) ;
10039             break;
10040             
10041         case '-' :
10042             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10043                 pic16_genMinus (ic);
10044             break;
10045             
10046         case '*' :
10047             genMult (ic);
10048             break;
10049             
10050         case '/' :
10051             genDiv (ic) ;
10052             break;
10053             
10054         case '%' :
10055             genMod (ic);
10056             break;
10057             
10058         case '>' :
10059             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10060             break;
10061             
10062         case '<' :
10063             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10064             break;
10065             
10066         case LE_OP:
10067         case GE_OP:
10068         case NE_OP:
10069             
10070             /* note these two are xlated by algebraic equivalence
10071                during parsing SDCC.y */
10072             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10073                    "got '>=' or '<=' shouldn't have come here");
10074             break;      
10075             
10076         case EQ_OP:
10077             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10078             break;          
10079             
10080         case AND_OP:
10081             genAndOp (ic);
10082             break;
10083             
10084         case OR_OP:
10085             genOrOp (ic);
10086             break;
10087             
10088         case '^' :
10089             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10090             break;
10091             
10092         case '|' :
10093                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10094             break;
10095             
10096         case BITWISEAND:
10097             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10098             break;
10099             
10100         case INLINEASM:
10101             genInline (ic);
10102             break;
10103             
10104         case RRC:
10105             genRRC (ic);
10106             break;
10107             
10108         case RLC:
10109             genRLC (ic);
10110             break;
10111             
10112         case GETHBIT:
10113             genGetHbit (ic);
10114             break;
10115             
10116         case LEFT_OP:
10117             genLeftShift (ic);
10118             break;
10119             
10120         case RIGHT_OP:
10121             genRightShift (ic);
10122             break;
10123             
10124         case GET_VALUE_AT_ADDRESS:
10125             genPointerGet(ic);
10126             break;
10127             
10128         case '=' :
10129             if (POINTER_SET(ic))
10130                 genPointerSet(ic);
10131             else
10132                 genAssign(ic);
10133             break;
10134             
10135         case IFX:
10136             genIfx (ic,NULL);
10137             break;
10138             
10139         case ADDRESS_OF:
10140             genAddrOf (ic);
10141             break;
10142             
10143         case JUMPTABLE:
10144             genJumpTab (ic);
10145             break;
10146             
10147         case CAST:
10148             genCast (ic);
10149             break;
10150             
10151         case RECEIVE:
10152             genReceive(ic);
10153             break;
10154             
10155         case SEND:
10156             addSet(&_G.sendSet,ic);
10157             break;
10158
10159         default :
10160             ic = ic;
10161         }
10162     }
10163     
10164
10165     /* now we are ready to call the 
10166        peep hole optimizer */
10167     if (!options.nopeep) {
10168       peepHole (&lineHead);
10169     }
10170     /* now do the actual printing */
10171     printLine (lineHead,codeOutFile);
10172
10173 #ifdef PCODE_DEBUG
10174     DFPRINTF((stderr,"printing pBlock\n\n"));
10175     pic16_printpBlock(stdout,pb);
10176 #endif
10177
10178     return;
10179 }