* doc/sdccman.lyx: updated SDCC version,
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
64
65 //static int aopIdx (asmop *aop, int offset);
66
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
70 /*
71   hack hack
72
73 */
74
75 /* max_key keeps track of the largest label number used in 
76    a function. This is then used to adjust the label offset
77    for the next function.
78 */
79 static int max_key=0;
80 static int GpsuedoStkPtr=0;
81
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
83
84 unsigned int pic16aopLiteral (value *val, int offset);
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
87
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
90
91 static bool is_LitOp(operand *op);
92 static bool is_LitAOp(asmop *aop);
93
94
95 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
96
97 /* set the following macro to 1 to enable passing the
98  * first byte of functions parameters via WREG */
99 #define USE_WREG_IN_FUNC_PARAMS 0
100
101
102 /* this is the down and dirty file with all kinds of 
103    kludgy & hacky stuff. This is what it is all about
104    CODE GENERATION for a specific MCU . some of the
105    routines may be reusable, will have to see */
106
107 static char *zero = "#0x00";
108 static char *one  = "#0x01";
109 //static char *spname = "sp";
110
111
112 /*
113  * Function return value policy (MSB-->LSB):
114  *  8 bits      -> WREG
115  * 16 bits      -> PRODL:WREG
116  * 24 bits      -> PRODH:PRODL:WREG
117  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
118  * >32 bits     -> on stack, and FSR0 points to the beginning
119  *
120  */
121  
122
123 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
124 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
125 static char **fReturn = fReturnpic16;
126
127 static char *accUse[] = {"WREG"};
128
129 //static short rbank = -1;
130
131 static struct {
132     short r0Pushed;
133     short r1Pushed;
134     short fsr0Pushed;
135     short accInUse;
136     short inLine;
137     short debugLine;
138     short nRegsSaved;
139     short ipushRegs;
140     set *sendSet;
141     set *stackRegSet;
142     int interruptvector;
143     int usefastretfie;
144     bitVect *fregsUsed;
145     int stack_lat;                      /* stack offset latency */
146     int resDirect;
147     int useWreg;                        /* flag when WREG is used to pass function parameter */
148 } _G;
149
150 /* Resolved ifx structure. This structure stores information
151    about an iCode ifx that makes it easier to generate code.
152 */
153 typedef struct resolvedIfx {
154   symbol *lbl;     /* pointer to a label */
155   int condition;   /* true or false ifx */
156   int generated;   /* set true when the code associated with the ifx
157                     * is generated */
158 } resolvedIfx;
159
160 extern int pic16_ptrRegReq ;
161 extern int pic16_nRegs;
162 extern FILE *codeOutFile;
163 //static void saverbank (int, iCode *,bool);
164
165 static lineNode *lineHead = NULL;
166 static lineNode *lineCurr = NULL;
167
168 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
169 0xE0, 0xC0, 0x80, 0x00};
170 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
171 0x07, 0x03, 0x01, 0x00};
172
173 static  pBlock *pb;
174
175 /*-----------------------------------------------------------------*/
176 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
177 /*                 exponent of 2 is returned, otherwise -1 is      */
178 /*                 returned.                                       */
179 /* note that this is similar to the function `powof2' in SDCCsymt  */
180 /* if(n == 2^y)                                                    */
181 /*   return y;                                                     */
182 /* return -1;                                                      */
183 /*-----------------------------------------------------------------*/
184 static int my_powof2 (unsigned long num)
185 {
186   if(num) {
187     if( (num & (num-1)) == 0) {
188       int nshifts = -1;
189       while(num) {
190         num>>=1;
191         nshifts++;
192       }
193       return nshifts;
194     }
195   }
196
197   return -1;
198 }
199
200 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
201 {
202   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
203                        line_no,
204                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
205                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
206                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
207                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
208                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
209                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
210                        ((result) ? AOP_SIZE(result) : 0));
211 }
212
213 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
214 {
215
216   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
217                        line_no,
218                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
219                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
220                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
221                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
222                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
223                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
224
225 }
226
227 void pic16_emitpcomment (char *fmt, ...)
228 {
229     va_list ap;
230     char lb[INITIAL_INLINEASM];  
231     char *lbp = lb;
232
233     va_start(ap,fmt);   
234
235     lb[0] = ';';
236     vsprintf(lb+1,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
254 {
255     va_list ap;
256     char lb[INITIAL_INLINEASM];  
257     char *lbp = lb;
258
259     if(!pic16_debug_verbose)
260       return;
261
262     va_start(ap,fmt);   
263
264     if (inst && *inst) {
265         if (fmt && *fmt)
266             sprintf(lb,"%s\t",inst);
267         else
268             sprintf(lb,"%s",inst);
269         vsprintf(lb+(strlen(lb)),fmt,ap);
270     }  else
271         vsprintf(lb,fmt,ap);
272
273     while (isspace(*lbp)) lbp++;
274
275     if (lbp && *lbp) 
276         lineCurr = (lineCurr ?
277                     connectLine(lineCurr,newLineNode(lb)) :
278                     (lineHead = newLineNode(lb)));
279     lineCurr->isInline = _G.inLine;
280     lineCurr->isDebug  = _G.debugLine;
281
282     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
283     va_end(ap);
284
285 //      fprintf(stderr, "%s\n", lb);
286 }
287
288 void pic16_emitpLabel(int key)
289 {
290   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
291 }
292
293 void pic16_emitpLabelFORCE(int key)
294 {
295   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
296 }
297
298 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
299 {
300
301   if(pcop)
302     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
303   else
304     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
305 }
306
307 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
308 {
309   if(pcop)
310     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
311   else
312     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
313 }
314   
315 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
316 {
317
318   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
319
320 }
321
322
323 #if 1
324 #define pic16_emitcode  DEBUGpic16_emitcode
325 #else
326 /*-----------------------------------------------------------------*/
327 /* pic16_emitcode - writes the code into a file : for now it is simple    */
328 /*-----------------------------------------------------------------*/
329 void pic16_emitcode (char *inst,char *fmt, ...)
330 {
331     va_list ap;
332     char lb[INITIAL_INLINEASM];  
333     char *lbp = lb;
334
335     va_start(ap,fmt);   
336
337     if (inst && *inst) {
338         if (fmt && *fmt)
339             sprintf(lb,"%s\t",inst);
340         else
341             sprintf(lb,"%s",inst);
342         vsprintf(lb+(strlen(lb)),fmt,ap);
343     }  else
344         vsprintf(lb,fmt,ap);
345
346     while (isspace(*lbp)) lbp++;
347
348     if (lbp && *lbp) 
349         lineCurr = (lineCurr ?
350                     connectLine(lineCurr,newLineNode(lb)) :
351                     (lineHead = newLineNode(lb)));
352     lineCurr->isInline = _G.inLine;
353     lineCurr->isDebug  = _G.debugLine;
354
355 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
356
357 //    if(pic16_debug_verbose)
358 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
359
360     va_end(ap);
361 }
362 #endif
363
364
365 /*-----------------------------------------------------------------*/
366 /* pic16_emitDebuggerSymbol - associate the current code location  */
367 /*   with a debugger symbol                                        */
368 /*-----------------------------------------------------------------*/
369 void
370 pic16_emitDebuggerSymbol (char * debugSym)
371 {
372   _G.debugLine = 1;
373   pic16_emitcode (";", "%s ==.", debugSym);
374   _G.debugLine = 0;
375 }
376
377
378 /*-----------------------------------------------------------------*/
379 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
380 /*-----------------------------------------------------------------*/
381 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
382 {
383 //    bool r0iu = FALSE , r1iu = FALSE;
384 //    bool r0ou = FALSE , r1ou = FALSE;
385     bool fsr0iu = FALSE, fsr0ou;
386     bool fsr2iu = FALSE, fsr2ou;
387     
388     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
389
390     
391     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
392     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
393     
394     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
395     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
396
397     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
398         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
399         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
400     }
401
402     if(!fsr0iu && !fsr0ou) {
403         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
404         (*aopp)->type = AOP_FSR0;
405
406         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
407         
408       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
409     }
410
411 #if 0
412     /* no usage of FSR2 */
413     if(!fsr2iu && !fsr2ou) {
414         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
415         (*aopp)->type = AOP_FSR2;
416
417       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
418     }
419 #endif
420         
421     /* now we know they both have usage */
422     /* if fsr0 not used in this instruction */
423     if (!fsr0iu) {
424         if (!_G.fsr0Pushed) {
425                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
426                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
427                 _G.fsr0Pushed++;
428         }
429
430         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
431         (*aopp)->type = AOP_FSR0;
432
433 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
434
435       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
436     }
437         
438
439     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
440     assert( 0 );
441
442     return NULL;
443 #if 0
444     /* the logic: if r0 & r1 used in the instruction
445     then we are in trouble otherwise */
446
447     /* first check if r0 & r1 are used by this
448     instruction, in which case we are in trouble */
449     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
450         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
451     {
452         goto endOfWorld;      
453     }
454
455     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
456     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
457
458     /* if no usage of r0 then return it */
459     if (!r0iu && !r0ou) {
460         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
461         (*aopp)->type = AOP_R0; 
462         
463         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
464     }
465
466     /* if no usage of r1 then return it */
467     if (!r1iu && !r1ou) {
468         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
469         (*aopp)->type = AOP_R1;
470
471         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
472     }    
473
474     /* now we know they both have usage */
475     /* if r0 not used in this instruction */
476     if (!r0iu) {
477         /* push it if not already pushed */
478         if (!_G.r0Pushed) {
479           //pic16_emitcode ("push","%s",
480           //          pic16_regWithIdx(R0_IDX)->dname);
481             _G.r0Pushed++ ;
482         }
483         
484         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
485         (*aopp)->type = AOP_R0;
486
487         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
488     }
489
490     /* if r1 not used then */
491
492     if (!r1iu) {
493         /* push it if not already pushed */
494         if (!_G.r1Pushed) {
495           //pic16_emitcode ("push","%s",
496           //          pic16_regWithIdx(R1_IDX)->dname);
497             _G.r1Pushed++ ;
498         }
499         
500         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
501         (*aopp)->type = AOP_R1;
502         return pic16_regWithIdx(R1_IDX);
503     }
504
505 endOfWorld :
506     /* I said end of world but not quite end of world yet */
507     /* if this is a result then we can push it on the stack*/
508     if (result) {
509         (*aopp)->type = AOP_STK;    
510         return NULL;
511     }
512
513     /* other wise this is true end of the world */
514     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
515            "getFreePtr should never reach here");
516     exit(0);
517 #endif
518 }
519
520 /*-----------------------------------------------------------------*/
521 /* newAsmop - creates a new asmOp                                  */
522 /*-----------------------------------------------------------------*/
523 static asmop *newAsmop (short type)
524 {
525     asmop *aop;
526
527     aop = Safe_calloc(1,sizeof(asmop));
528     aop->type = type;
529     return aop;
530 }
531
532 static void genSetDPTR(int n)
533 {
534     if (!n)
535     {
536         pic16_emitcode(";", "Select standard DPTR");
537         pic16_emitcode("mov", "dps, #0x00");
538     }
539     else
540     {
541         pic16_emitcode(";", "Select alternate DPTR");
542         pic16_emitcode("mov", "dps, #0x01");
543     }
544 }
545
546 /*-----------------------------------------------------------------*/
547 /* resolveIfx - converts an iCode ifx into a form more useful for  */
548 /*              generating code                                    */
549 /*-----------------------------------------------------------------*/
550 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
551 {
552
553   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
554
555   if(!resIfx) 
556     return;
557
558
559   resIfx->condition = 1;    /* assume that the ifx is true */
560   resIfx->generated = 0;    /* indicate that the ifx has not been used */
561
562   if(!ifx) {
563     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
564
565 #if 1
566     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
567                         __FUNCTION__,__LINE__,resIfx->lbl->key);
568 #endif
569
570   } else {
571     if(IC_TRUE(ifx)) {
572       resIfx->lbl = IC_TRUE(ifx);
573     } else {
574       resIfx->lbl = IC_FALSE(ifx);
575       resIfx->condition = 0;
576     }
577
578 #if 1
579     if(IC_TRUE(ifx)) 
580       DEBUGpic16_emitcode("; ***","ifx true is non-null");
581     if(IC_FALSE(ifx)) 
582       DEBUGpic16_emitcode("; ***","ifx false is non-null");
583 #endif
584   }
585
586   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
587
588 }
589 #if 0
590 /*-----------------------------------------------------------------*/
591 /* pointerCode - returns the code for a pointer type               */
592 /*-----------------------------------------------------------------*/
593 static int pointerCode (sym_link *etype)
594 {
595
596     return PTR_TYPE(SPEC_OCLS(etype));
597
598 }
599 #endif
600
601 /*-----------------------------------------------------------------*/
602 /* aopForSym - for a true symbol                                   */
603 /*-----------------------------------------------------------------*/
604 static asmop *aopForSym (iCode *ic, operand *op, bool result)
605 {
606     symbol *sym=OP_SYMBOL(op);
607     asmop *aop;
608     memmap *space= SPEC_OCLS(sym->etype);
609
610     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
611
612     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
613     
614 //    sym = OP_SYMBOL(op);
615
616     /* if already has one */
617     if (sym->aop) {
618             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
619         return sym->aop;
620     }
621
622 #if 0
623     /* if symbol was initially placed onStack then we must re-place it
624      * to direct memory, since pic16 does not have a specific stack */
625     if(sym->onStack) {
626         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
627     }
628 #endif
629
630 #if 1
631     /* assign depending on the storage class */
632     /* if it is on the stack or indirectly addressable */
633     /* space we need to assign either r0 or r1 to it   */    
634     if (sym->onStack || sym->iaccess) {
635       pCodeOp *pcop[4];
636       int i;
637       
638         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
639                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
640         
641         /* acquire a temporary register -- it is saved in function */
642
643         sym->aop = aop = newAsmop(AOP_STA);
644         aop->aopu.stk.stk = sym->stack;
645         aop->size = getSize(sym->type);
646
647
648         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
649         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
650         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
651           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
652           
653           for(i=0;i<aop->size;i++)
654             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
655             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
656         } else
657           for(i=0;i<aop->size;i++) {
658             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
659             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
660           }
661
662
663 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
664
665 #if 1
666         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
667         
668         if(_G.accInUse) {
669                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
670         }
671         
672         for(i=0;i<aop->size;i++) {
673
674           /* initialise for stack access via frame pointer */
675           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
676
677           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
678                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
679         }
680         
681         if(_G.accInUse) {
682                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
683         }
684         
685         return (aop);
686 #endif
687
688 #if 0
689         /* now assign the address of the variable to 
690         the pointer register */
691         if (aop->type != AOP_STK) {
692
693             if (sym->onStack) {
694                     if ( _G.accInUse )
695                         pic16_emitcode("push","acc");
696
697                     pic16_emitcode("mov","a,_bp");
698                     pic16_emitcode("add","a,#0x%02x",
699                              ((sym->stack < 0) ?
700                               ((char)(sym->stack - _G.nRegsSaved )) :
701                               ((char)sym->stack)) & 0xff);
702                     pic16_emitcode("mov","%s,a",
703                              aop->aopu.aop_ptr->name);
704
705                     if ( _G.accInUse )
706                         pic16_emitcode("pop","acc");
707             } else
708                 pic16_emitcode("mov","%s,#%s",
709                          aop->aopu.aop_ptr->name,
710                          sym->rname);
711             aop->paged = space->paged;
712         } else
713             aop->aopu.aop_stk = sym->stack;
714         return aop;
715 #endif
716
717     }
718 #endif
719
720 #if 0
721     if (sym->onStack && options.stack10bit)
722     {
723         /* It's on the 10 bit stack, which is located in
724          * far data space.
725          */
726          
727       //DEBUGpic16_emitcode(";","%d",__LINE__);
728
729         if ( _G.accInUse )
730                 pic16_emitcode("push","acc");
731
732         pic16_emitcode("mov","a,_bp");
733         pic16_emitcode("add","a,#0x%02x",
734                  ((sym->stack < 0) ?
735                    ((char)(sym->stack - _G.nRegsSaved )) :
736                    ((char)sym->stack)) & 0xff);
737         
738         genSetDPTR(1);
739         pic16_emitcode ("mov","dpx1,#0x40");
740         pic16_emitcode ("mov","dph1,#0x00");
741         pic16_emitcode ("mov","dpl1, a");
742         genSetDPTR(0);
743         
744         if ( _G.accInUse )
745             pic16_emitcode("pop","acc");
746             
747         sym->aop = aop = newAsmop(AOP_DPTR2);
748         aop->size = getSize(sym->type); 
749         return aop;
750     }
751 #endif
752
753 #if 0
754     /* special case for a function */
755     if (IS_FUNC(sym->type)) {   
756         sym->aop = aop = newAsmop(AOP_PCODE);
757         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
758         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
759         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
760         PCOI(aop->aopu.pcop)->index = 0;
761         aop->size = FPTRSIZE; 
762         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
763         return aop;
764     }
765 #endif
766
767
768
769     //DEBUGpic16_emitcode(";","%d",__LINE__);
770     /* if in bit space */
771     if (IN_BITSPACE(space)) {
772         sym->aop = aop = newAsmop (AOP_CRY);
773         aop->aopu.aop_dir = sym->rname ;
774         aop->size = getSize(sym->type);
775         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
776         return aop;
777     }
778     /* if it is in direct space */
779     if (IN_DIRSPACE(space)) {
780         sym->aop = aop = newAsmop (AOP_DIR);
781         aop->aopu.aop_dir = sym->rname ;
782         aop->size = getSize(sym->type);
783         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
784         pic16_allocDirReg( IC_LEFT(ic) );
785         return aop;
786     }
787
788
789     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
790         sym->aop = aop = newAsmop (AOP_DIR);
791         aop->aopu.aop_dir = sym->rname ;
792         aop->size = getSize(sym->type);
793         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
794         pic16_allocDirReg( IC_LEFT(ic) );
795         return aop;
796     }
797
798
799     /* only remaining is far space */
800     sym->aop = aop = newAsmop(AOP_PCODE);
801
802 /* change the next if to 1 to revert to good old immediate code */
803         if(IN_CODESPACE(space)) {
804                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
805                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
806                 PCOI(aop->aopu.pcop)->index = 0;
807         } else {
808                 /* try to allocate via direct register */
809                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
810 //              aop->size = getSize( sym->type );
811         }
812
813         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
814                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
815
816 #if 0
817         if(!pic16_allocDirReg (IC_LEFT(ic)))
818                 return NULL;
819 #endif
820
821         if(IN_DIRSPACE( space ))
822                 aop->size = PTRSIZE;
823         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
824                 aop->size = FPTRSIZE;
825         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
826         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
827         else if(sym->onStack) {
828                 aop->size = PTRSIZE;
829         } else {
830                 assert( 0 );
831         }
832
833     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
834
835     /* if it is in code space */
836     if (IN_CODESPACE(space))
837         aop->code = 1;
838
839     return aop;     
840 }
841
842 /*-----------------------------------------------------------------*/
843 /* aopForRemat - rematerialzes an object                           */
844 /*-----------------------------------------------------------------*/
845 static asmop *aopForRemat (operand *op) // x symbol *sym)
846 {
847   symbol *sym = OP_SYMBOL(op);
848   operand *refop;
849   iCode *ic = NULL, *oldic;
850   asmop *aop = newAsmop(AOP_PCODE);
851   int val = 0;
852   int offset = 0;
853   int viaimmd=0;
854
855
856         ic = sym->rematiCode;
857
858         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
859         
860         if(IS_OP_POINTER(op)) {
861                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
862         }
863
864         for (;;) {
865                 oldic = ic;
866
867 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
868         
869                 if (ic->op == '+') {
870                         val += (int) operandLitValue(IC_RIGHT(ic));
871                 } else if (ic->op == '-') {
872                         val -= (int) operandLitValue(IC_RIGHT(ic));
873                 } else
874                         break;
875                 
876                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
877         }
878
879         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
880         refop = IC_LEFT(ic);
881
882         if(!op->isaddr)viaimmd++; else viaimmd=0;
883                 
884 /* set the following if to 1 to revert to good old immediate code */
885         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
886                 || viaimmd) {
887
888                 DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
889
890                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
891
892 #if 0
893                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
894 #else
895                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
896 #endif
897
898                 PCOI(aop->aopu.pcop)->index = val;
899         } else {
900                 DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
901
902                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
903                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
904 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
905         }
906
907
908         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
909                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
910 #if 0
911                 val, IS_PTR_CONST(operandType(op)));
912 #else
913                 val, IS_CODEPTR(operandType(op)));
914 #endif
915
916 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
917
918         pic16_allocDirReg (IC_LEFT(ic));
919
920         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
921                 aop->code = 1;
922
923   return aop;        
924 }
925
926 #if 0
927 static int aopIdx (asmop *aop, int offset)
928 {
929   if(!aop)
930     return -1;
931
932   if(aop->type !=  AOP_REG)
933     return -2;
934         
935   return aop->aopu.aop_reg[offset]->rIdx;
936
937 }
938 #endif
939
940 /*-----------------------------------------------------------------*/
941 /* regsInCommon - two operands have some registers in common       */
942 /*-----------------------------------------------------------------*/
943 static bool regsInCommon (operand *op1, operand *op2)
944 {
945     symbol *sym1, *sym2;
946     int i;
947
948     /* if they have registers in common */
949     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
950         return FALSE ;
951
952     sym1 = OP_SYMBOL(op1);
953     sym2 = OP_SYMBOL(op2);
954
955     if (sym1->nRegs == 0 || sym2->nRegs == 0)
956         return FALSE ;
957
958     for (i = 0 ; i < sym1->nRegs ; i++) {
959         int j;
960         if (!sym1->regs[i])
961             continue ;
962
963         for (j = 0 ; j < sym2->nRegs ;j++ ) {
964             if (!sym2->regs[j])
965                 continue ;
966
967             if (sym2->regs[j] == sym1->regs[i])
968                 return TRUE ;
969         }
970     }
971
972     return FALSE ;
973 }
974
975 /*-----------------------------------------------------------------*/
976 /* operandsEqu - equivalent                                        */
977 /*-----------------------------------------------------------------*/
978 static bool operandsEqu ( operand *op1, operand *op2)
979 {
980     symbol *sym1, *sym2;
981
982     /* if they not symbols */
983     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
984         return FALSE;
985
986     sym1 = OP_SYMBOL(op1);
987     sym2 = OP_SYMBOL(op2);
988
989     /* if both are itemps & one is spilt
990        and the other is not then false */
991     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
992         sym1->isspilt != sym2->isspilt )
993         return FALSE ;
994
995     /* if they are the same */
996     if (sym1 == sym2)
997         return TRUE ;
998
999     if (sym1->rname[0] && sym2->rname[0]
1000         && strcmp (sym1->rname, sym2->rname) == 0)
1001         return TRUE;
1002
1003
1004     /* if left is a tmp & right is not */
1005     if (IS_ITEMP(op1)  && 
1006         !IS_ITEMP(op2) &&
1007         sym1->isspilt  &&
1008         (sym1->usl.spillLoc == sym2))
1009         return TRUE;
1010
1011     if (IS_ITEMP(op2)  && 
1012         !IS_ITEMP(op1) &&
1013         sym2->isspilt  &&
1014         sym1->level > 0 &&
1015         (sym2->usl.spillLoc == sym1))
1016         return TRUE ;
1017
1018     return FALSE ;
1019 }
1020
1021 /*-----------------------------------------------------------------*/
1022 /* pic16_sameRegs - two asmops have the same registers                   */
1023 /*-----------------------------------------------------------------*/
1024 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1025 {
1026     int i;
1027
1028     if (aop1 == aop2)
1029         return TRUE ;
1030
1031     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1032                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1033
1034     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1035
1036     if (aop1->type != AOP_REG ||
1037         aop2->type != AOP_REG )
1038         return FALSE ;
1039
1040     if (aop1->size != aop2->size )
1041         return FALSE ;
1042
1043     for (i = 0 ; i < aop1->size ; i++ ) {
1044 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1045
1046 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1047         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1048             return FALSE ;
1049     }
1050
1051     return TRUE ;
1052 }
1053
1054 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1055 {
1056     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1057                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1058
1059     if(aop1 == aop2)return TRUE;
1060     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1061       
1062       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1063     
1064   return TRUE;
1065 }
1066
1067
1068 /*-----------------------------------------------------------------*/
1069 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1070 /*-----------------------------------------------------------------*/
1071 void pic16_aopOp (operand *op, iCode *ic, bool result)
1072 {
1073     asmop *aop;
1074     symbol *sym;
1075     int i;
1076
1077     if (!op)
1078         return ;
1079
1080 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1081
1082     /* if this a literal */
1083     if (IS_OP_LITERAL(op)) {
1084         op->aop = aop = newAsmop(AOP_LIT);
1085         aop->aopu.aop_lit = op->operand.valOperand;
1086         aop->size = getSize(operandType(op));
1087         return;
1088     }
1089
1090     {
1091       sym_link *type = operandType(op);
1092 #if 0
1093       if(IS_PTR_CONST(type))
1094 #else
1095       if(IS_CODEPTR(type))
1096 #endif
1097         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1098     }
1099
1100     /* if already has a asmop then continue */
1101     if (op->aop)
1102         return ;
1103
1104     /* if the underlying symbol has a aop */
1105     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1106       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1107         op->aop = OP_SYMBOL(op)->aop;
1108         return;
1109     }
1110
1111     /* if this is a true symbol */
1112     if (IS_TRUE_SYMOP(op)) {    
1113         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1114       op->aop = aopForSym(ic, op, result);
1115       return ;
1116     }
1117
1118     /* this is a temporary : this has
1119     only four choices :
1120     a) register
1121     b) spillocation
1122     c) rematerialize 
1123     d) conditional   
1124     e) can be a return use only */
1125
1126     sym = OP_SYMBOL(op);
1127
1128         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1129     /* if the type is a conditional */
1130     if (sym->regType == REG_CND) {
1131         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1132         aop->size = 0;
1133         return;
1134     }
1135
1136     /* if it is spilt then two situations
1137     a) is rematerialize 
1138     b) has a spill location */
1139     if (sym->isspilt || sym->nRegs == 0) {
1140
1141       DEBUGpic16_emitcode(";","%d",__LINE__);
1142         /* rematerialize it NOW */
1143         if (sym->remat) {
1144
1145             sym->aop = op->aop = aop = aopForRemat (op);
1146             aop->size = getSize(sym->type);
1147             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1148             return;
1149         }
1150
1151 #if 1
1152         if (sym->accuse) {
1153             int i;
1154             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1155             aop->size = getSize(sym->type);
1156             for ( i = 0 ; i < 1 ; i++ ) {
1157                 aop->aopu.aop_str[i] = accUse[i];
1158 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1159             }
1160             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1161             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1162             return;  
1163         }
1164 #endif
1165
1166 #if 1
1167         if (sym->ruonly ) {
1168           /*
1169           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1170           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1171           //pic16_allocDirReg (IC_LEFT(ic));
1172           aop->size = getSize(sym->type);
1173           */
1174
1175           unsigned i;
1176
1177           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1178           aop->size = getSize(sym->type);
1179           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1180             aop->aopu.aop_str[i] = fReturn[i];
1181
1182           DEBUGpic16_emitcode(";","%d",__LINE__);
1183           return;
1184         }
1185 #endif
1186         /* else spill location  */
1187         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1188             /* force a new aop if sizes differ */
1189             sym->usl.spillLoc->aop = NULL;
1190         }
1191
1192 #if 0
1193         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1194                             __FUNCTION__,__LINE__,
1195                             sym->usl.spillLoc->rname,
1196                             sym->rname, sym->usl.spillLoc->offset);
1197 #endif
1198
1199         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1200         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1201         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1202                                           getSize(sym->type), 
1203                                           sym->usl.spillLoc->offset, op);
1204         aop->size = getSize(sym->type);
1205
1206         return;
1207     }
1208
1209     {
1210       sym_link *type = operandType(op);
1211 #if 0
1212       if(IS_PTR_CONST(type)) 
1213 #else
1214       if(IS_CODEPTR(type)) 
1215 #endif
1216         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1217     }
1218
1219     /* must be in a register */
1220     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1221     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1222     aop->size = sym->nRegs;
1223     for ( i = 0 ; i < sym->nRegs ;i++)
1224         aop->aopu.aop_reg[i] = sym->regs[i];
1225 }
1226
1227 /*-----------------------------------------------------------------*/
1228 /* pic16_freeAsmop - free up the asmop given to an operand               */
1229 /*----------------------------------------------------------------*/
1230 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1231 {   
1232     asmop *aop ;
1233
1234     if (!op)
1235         aop = aaop;
1236     else 
1237         aop = op->aop;
1238
1239     if (!aop)
1240         return ;
1241
1242     if (aop->freed)
1243         goto dealloc; 
1244
1245     aop->freed = 1;
1246
1247     /* depending on the asmop type only three cases need work AOP_RO
1248        , AOP_R1 && AOP_STK */
1249 #if 1
1250     switch (aop->type) {
1251         case AOP_FSR0 :
1252             if (_G.fsr0Pushed ) {
1253                 if (pop) {
1254                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1255                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1256 //                    pic16_emitcode ("pop","ar0");
1257                     _G.fsr0Pushed--;
1258                 }
1259             }
1260             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1261             break;
1262
1263         case AOP_FSR2 :
1264             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1265             break;
1266
1267         case AOP_R0 :
1268             if (_G.r0Pushed ) {
1269                 if (pop) {
1270                     pic16_emitcode ("pop","ar0");     
1271                     _G.r0Pushed--;
1272                 }
1273             }
1274             bitVectUnSetBit(ic->rUsed,R0_IDX);
1275             break;
1276
1277         case AOP_R1 :
1278             if (_G.r1Pushed ) {
1279                 if (pop) {
1280                     pic16_emitcode ("pop","ar1");
1281                     _G.r1Pushed--;
1282                 }
1283             }
1284             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1285             break;
1286
1287         case AOP_STA:
1288           {
1289             int i;
1290
1291               /* we must store the result on stack */
1292               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1293                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1294                 for(i=0;i<aop->size;i++) {
1295                   /* initialise for stack access via frame pointer */
1296                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1297
1298                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1299                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1300                 }
1301         
1302                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1303               }
1304
1305               if(!_G.resDirect) {
1306                 for(i=0;i<aop->size;i++)
1307                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1308               }
1309               _G.resDirect = 0;
1310           }
1311           break;
1312 #if 0
1313         case AOP_STK :
1314         {
1315             int sz = aop->size;    
1316             int stk = aop->aopu.aop_stk + aop->size;
1317             bitVectUnSetBit(ic->rUsed,R0_IDX);
1318             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1319
1320             getFreePtr(ic,&aop,FALSE);
1321             
1322             if (options.stack10bit)
1323             {
1324                 /* I'm not sure what to do here yet... */
1325                 /* #STUB */
1326                 fprintf(stderr, 
1327                         "*** Warning: probably generating bad code for "
1328                         "10 bit stack mode.\n");
1329             }
1330             
1331             if (stk) {
1332                 pic16_emitcode ("mov","a,_bp");
1333                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1334                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1335             } else {
1336                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1337             }
1338
1339             while (sz--) {
1340                 pic16_emitcode("pop","acc");
1341                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1342                 if (!sz) break;
1343                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1344             }
1345             op->aop = aop;
1346             pic16_freeAsmop(op,NULL,ic,TRUE);
1347             if (_G.r0Pushed) {
1348                 pic16_emitcode("pop","ar0");
1349                 _G.r0Pushed--;
1350             }
1351
1352             if (_G.r1Pushed) {
1353                 pic16_emitcode("pop","ar1");
1354                 _G.r1Pushed--;
1355             }       
1356         }
1357 #endif
1358
1359     }
1360 #endif
1361
1362 dealloc:
1363     /* all other cases just dealloc */
1364     if (op ) {
1365         op->aop = NULL;
1366         if (IS_SYMOP(op)) {
1367             OP_SYMBOL(op)->aop = NULL;    
1368             /* if the symbol has a spill */
1369             if (SPIL_LOC(op))
1370                 SPIL_LOC(op)->aop = NULL;
1371         }
1372     }
1373 }
1374
1375 /*-----------------------------------------------------------------*/
1376 /* pic16_aopGet - for fetching value of the aop                          */
1377 /*-----------------------------------------------------------------*/
1378 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1379 {
1380     char *s = buffer ;
1381     char *rs;
1382
1383     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1384
1385     /* offset is greater than size then zero */
1386     if (offset > (aop->size - 1) &&
1387         aop->type != AOP_LIT)
1388         return zero;
1389
1390     /* depending on type */
1391     switch (aop->type) {
1392
1393     case AOP_FSR0:
1394     case AOP_FSR2:
1395       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1396       rs = Safe_calloc(1, strlen(s)+1);
1397       strcpy(rs, s);
1398       return (rs);
1399       
1400 #if 0
1401       /* if we need to increment it */
1402       while (offset > aop->coff)
1403         {
1404           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1405           aop->coff++;
1406         }
1407
1408       while (offset < aop->coff)
1409         {
1410           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1411           aop->coff--;
1412         }
1413       aop->coff = offset;
1414       if (aop->paged)
1415         {
1416           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1417           return (dname ? "acc" : "a");
1418         }
1419       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1420       rs = Safe_calloc (1, strlen (s) + 1);
1421       strcpy (rs, s);
1422       return rs;
1423 #endif
1424
1425         
1426     case AOP_IMMD:
1427         if (bit16) 
1428             sprintf (s,"%s",aop->aopu.aop_immd);
1429         else
1430             if (offset) 
1431                 sprintf(s,"(%s >> %d)",
1432                         aop->aopu.aop_immd,
1433                         offset*8);
1434             else
1435                 sprintf(s,"%s",
1436                         aop->aopu.aop_immd);
1437         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1438         rs = Safe_calloc(1,strlen(s)+1);
1439         strcpy(rs,s);   
1440         return rs;
1441         
1442     case AOP_DIR:
1443       if (offset) {
1444         sprintf(s,"(%s + %d)",
1445                 aop->aopu.aop_dir,
1446                 offset);
1447         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1448       } else
1449             sprintf(s,"%s",aop->aopu.aop_dir);
1450         rs = Safe_calloc(1,strlen(s)+1);
1451         strcpy(rs,s);   
1452         return rs;
1453         
1454     case AOP_REG:
1455       //if (dname) 
1456       //    return aop->aopu.aop_reg[offset]->dname;
1457       //else
1458             return aop->aopu.aop_reg[offset]->name;
1459         
1460     case AOP_CRY:
1461       //pic16_emitcode(";","%d",__LINE__);
1462       return aop->aopu.aop_dir;
1463         
1464     case AOP_ACC:
1465         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1466 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1467 //        assert( 0 );
1468 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1469         rs = Safe_strdup("WREG");
1470         return (rs);
1471
1472     case AOP_LIT:
1473         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1474         rs = Safe_calloc(1,strlen(s)+1);
1475         strcpy(rs,s);   
1476         return rs;
1477         
1478     case AOP_STR:
1479         aop->coff = offset ;
1480         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1481             dname)
1482             return "acc";
1483         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1484         
1485         return aop->aopu.aop_str[offset];
1486         
1487     case AOP_PCODE:
1488       {
1489         pCodeOp *pcop = aop->aopu.pcop;
1490         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1491         if(pcop->name) {
1492           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1493           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1494           sprintf(s,"%s", pcop->name);
1495         } else
1496           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1497
1498       }
1499       rs = Safe_calloc(1,strlen(s)+1);
1500       strcpy(rs,s);   
1501       return rs;
1502
1503     case AOP_STA:
1504         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1505         return (rs);
1506         
1507     case AOP_STK:
1508 //        pCodeOp *pcop = aop->aop
1509         break;
1510
1511     }
1512
1513     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1514     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1515            "aopget got unsupported aop->type");
1516     exit(0);
1517 }
1518
1519
1520
1521 /* lock has the following meaning: When allocating temporary registers
1522  * for stack variables storage, the value of the temporary register is
1523  * saved on stack. Its value is restored at the end. This procedure is
1524  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1525  * a possibility that before a call to pic16_aopOp, a temporary register
1526  * is allocated for a while and it is freed after some time, this will
1527  * mess the stack and values will not be restored properly. So use lock=1
1528  * to allocate temporary registers used internally by the programmer, and
1529  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1530  * to inform the compiler developer about a possible bug. This is an internal
1531  * feature for developing the compiler -- VR */
1532  
1533 int _TempReg_lock = 0;
1534 /*-----------------------------------------------------------------*/
1535 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1536 /*-----------------------------------------------------------------*/
1537 pCodeOp *pic16_popGetTempReg(int lock)
1538 {
1539   pCodeOp *pcop;
1540   symbol *cfunc;
1541
1542 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1543     if(_TempReg_lock) {
1544       werror(W_POSSBUG2, __FILE__, __LINE__);
1545     }
1546     
1547     _TempReg_lock += lock;
1548     
1549     cfunc = currFunc;
1550     currFunc = NULL;
1551
1552     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1553     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1554       PCOR(pcop)->r->wasUsed=1;
1555       PCOR(pcop)->r->isFree=0;
1556
1557       /* push value on stack */
1558       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1559     }
1560
1561     currFunc = cfunc;
1562
1563   return pcop;
1564 }
1565
1566 /*-----------------------------------------------------------------*/
1567 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1568 /*                            don't save if inside v               */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1571 {
1572   pCodeOp *pcop;
1573   symbol *cfunc;
1574
1575 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1576
1577     if(_TempReg_lock) {
1578       werror(W_POSSBUG2, __FILE__, __LINE__);
1579     }
1580
1581     _TempReg_lock += lock;
1582
1583     cfunc = currFunc;
1584     currFunc = NULL;
1585
1586     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1587     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1588       PCOR(pcop)->r->wasUsed=1;
1589       PCOR(pcop)->r->isFree=0;
1590
1591       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1592       /* push value on stack */
1593         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1594       }
1595     }
1596
1597     currFunc = cfunc;
1598
1599   return pcop;
1600 }
1601
1602
1603 /*-----------------------------------------------------------------*/
1604 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1605 /*-----------------------------------------------------------------*/
1606 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1607 {
1608   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1609
1610   _TempReg_lock -= lock;
1611
1612   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1613     PCOR(pcop)->r->isFree = 1;
1614     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1615   }
1616 }
1617 /*-----------------------------------------------------------------*/
1618 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1619 /*-----------------------------------------------------------------*/
1620 pCodeOp *pic16_popGetLabel(unsigned int key)
1621 {
1622
1623   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1624
1625   if(key>max_key)
1626     max_key = key;
1627
1628   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1629 }
1630
1631 /*-----------------------------------------------------------------*/
1632 /* pic16_popCopyReg - copy a pcode operator                              */
1633 /*-----------------------------------------------------------------*/
1634 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1635 {
1636   pCodeOpReg *pcor;
1637
1638   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1639   pcor->pcop.type = pc->pcop.type;
1640   if(pc->pcop.name) {
1641     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1642       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1643   } else
1644     pcor->pcop.name = NULL;
1645
1646   pcor->r = pc->r;
1647   pcor->rIdx = pc->rIdx;
1648   pcor->r->wasUsed=1;
1649
1650 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1651
1652   return PCOP(pcor);
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1657 /*-----------------------------------------------------------------*/
1658 pCodeOp *pic16_popGetLit(int lit)
1659 {
1660   return pic16_newpCodeOpLit(lit);
1661 }
1662
1663 /*-----------------------------------------------------------------*/
1664 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1665 /*-----------------------------------------------------------------*/
1666 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1667 {
1668   return pic16_newpCodeOpLit2(lit, arg2);
1669 }
1670
1671
1672 /*-----------------------------------------------------------------*/
1673 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1674 /*-----------------------------------------------------------------*/
1675 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1676 {
1677   return pic16_newpCodeOpImmd(name, offset,index, 0);
1678 }
1679
1680
1681 /*-----------------------------------------------------------------*/
1682 /* pic16_popGet - asm operator to pcode operator conversion              */
1683 /*-----------------------------------------------------------------*/
1684 pCodeOp *pic16_popGetWithString(char *str)
1685 {
1686   pCodeOp *pcop;
1687
1688
1689   if(!str) {
1690     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1691     exit (1);
1692   }
1693
1694   pcop = pic16_newpCodeOp(str,PO_STR);
1695
1696   return pcop;
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popRegFromString -                                        */
1701 /*-----------------------------------------------------------------*/
1702 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1703 {
1704
1705   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1706   pcop->type = PO_DIR;
1707
1708   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1709   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1710
1711   if(!str)
1712     str = "BAD_STRING";
1713
1714   pcop->name = Safe_calloc(1,strlen(str)+1);
1715   strcpy(pcop->name,str);
1716
1717   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1718
1719   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1720
1721   /* make sure that register doesn't exist,
1722    * and operand isn't NULL
1723    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1724   if((PCOR(pcop)->r == NULL) 
1725     && (op)
1726     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1727 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1728 //              __FUNCTION__, __LINE__, str, size, offset);
1729
1730     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1731     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1732
1733   }
1734   PCOR(pcop)->instance = offset;
1735
1736   return pcop;
1737 }
1738
1739 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1740 {
1741   pCodeOp *pcop;
1742
1743 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1744
1745         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1746         PCOR(pcop)->rIdx = rIdx;
1747         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1748
1749         PCOR(pcop)->r->isFree = 0;
1750         PCOR(pcop)->r->wasUsed = 1;
1751
1752         pcop->type = PCOR(pcop)->r->pc_type;
1753
1754   return pcop;
1755 }
1756
1757 /*---------------------------------------------------------------------------------*/
1758 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1759 /*                 VR 030601                                                       */
1760 /*---------------------------------------------------------------------------------*/
1761 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1762 {
1763   pCodeOpReg2 *pcop2;
1764   pCodeOp *temp;
1765   
1766         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1767
1768         /* comment the following check, so errors to throw up */
1769 //      if(!pcop2)return NULL;
1770
1771         temp = pic16_popGet(aop_dst, offset);
1772         pcop2->pcop2 = temp;
1773         
1774   return PCOP(pcop2);
1775 }
1776
1777
1778
1779 /*--------------------------------------------------------------------------------.-*/
1780 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1781 /*                  VR 030601 , adapted by Hans Dorn                                */
1782 /*--------------------------------------------------------------------------------.-*/
1783 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1784 {
1785   pCodeOpReg2 *pcop2;
1786  
1787         pcop2 = (pCodeOpReg2 *)src;
1788         pcop2->pcop2 = dst;
1789         
1790         return PCOP(pcop2);
1791 }
1792
1793
1794
1795 /*---------------------------------------------------------------------------------*/
1796 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1797 /*                     movff instruction                                           */
1798 /*---------------------------------------------------------------------------------*/
1799 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1800 {
1801   pCodeOpReg2 *pcop2;
1802
1803         if(!noalloc) {
1804                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1805                 pcop2->pcop2 = pic16_popCopyReg(dst);
1806         } else {
1807                 /* the pCodeOp may be already allocated */
1808                 pcop2 = (pCodeOpReg2 *)(src);
1809                 pcop2->pcop2 = (pCodeOp *)(dst);
1810         }
1811
1812   return PCOP(pcop2);
1813 }
1814
1815
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGet - asm operator to pcode operator conversion              */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1820 {
1821   //char *s = buffer ;
1822   char *rs;
1823   pCodeOp *pcop;
1824
1825     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1826     /* offset is greater than
1827     size then zero */
1828
1829 //    if (offset > (aop->size - 1) &&
1830 //        aop->type != AOP_LIT)
1831 //      return NULL;  //zero;
1832
1833     /* depending on type */
1834     switch (aop->type) {
1835         
1836     case AOP_R0:
1837     case AOP_R1:
1838     case AOP_DPTR:
1839     case AOP_DPTR2:
1840         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1841         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1842         assert( 0 );
1843         return NULL;
1844
1845
1846     case AOP_FSR0:
1847     case AOP_FSR2:
1848       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1849       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1850       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1851       PCOR(pcop)->r->wasUsed = 1;
1852       PCOR(pcop)->r->isFree = 0;
1853       
1854       PCOR(pcop)->instance = offset;
1855       pcop->type = PCOR(pcop)->r->pc_type;
1856       return (pcop);
1857
1858     case AOP_IMMD:
1859       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1860       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1861
1862     case AOP_STA:
1863       /* pCodeOp is already allocated from aopForSym */
1864         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1865         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1866           
1867       return (pcop);
1868       
1869     case AOP_ACC:
1870       {
1871         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1872
1873         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1874
1875         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1876         
1877         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1878         PCOR(pcop)->rIdx = rIdx;
1879         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1880         PCOR(pcop)->r->wasUsed=1;
1881         PCOR(pcop)->r->isFree=0;
1882
1883         PCOR(pcop)->instance = offset;
1884         pcop->type = PCOR(pcop)->r->pc_type;
1885 //      rs = aop->aopu.aop_reg[offset]->name;
1886 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1887         return pcop;
1888
1889
1890 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1891 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1892
1893 //      assert( 0 );
1894       }
1895         
1896     case AOP_DIR:
1897       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1898       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1899         
1900     case AOP_REG:
1901       {
1902         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1903
1904         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1905         
1906         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907 //      pcop->type = PO_GPR_REGISTER;
1908         PCOR(pcop)->rIdx = rIdx;
1909         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1910         PCOR(pcop)->r->wasUsed=1;
1911         PCOR(pcop)->r->isFree=0;
1912
1913         PCOR(pcop)->instance = offset;
1914         pcop->type = PCOR(pcop)->r->pc_type;
1915         rs = aop->aopu.aop_reg[offset]->name;
1916         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1917         return pcop;
1918       }
1919
1920     case AOP_CRY:
1921         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1922
1923       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1924       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1925       //if(PCOR(pcop)->r == NULL)
1926       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1927       return pcop;
1928         
1929     case AOP_LIT:
1930         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1931       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1932
1933     case AOP_STR:
1934       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1935       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1936
1937       /*
1938       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1939       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1940       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1941       pcop->type = PCOR(pcop)->r->pc_type;
1942       pcop->name = PCOR(pcop)->r->name;
1943
1944       return pcop;
1945       */
1946
1947     case AOP_PCODE:
1948       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1949                           __LINE__, 
1950                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1951       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1952 #if 1
1953         switch( aop->aopu.pcop->type ) {
1954                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1955                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1956                 default:
1957                         assert( 0 );    /* should never reach here */;
1958         }
1959 #else
1960       PCOI(pcop)->offset = offset;
1961 #endif
1962       return pcop;
1963     }
1964
1965     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1966            "pic16_popGet got unsupported aop->type");
1967     exit(0);
1968 }
1969 /*-----------------------------------------------------------------*/
1970 /* pic16_aopPut - puts a string for a aop                                */
1971 /*-----------------------------------------------------------------*/
1972 void pic16_aopPut (asmop *aop, char *s, int offset)
1973 {
1974     char *d = buffer ;
1975     symbol *lbl ;
1976
1977     return;
1978
1979     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1980
1981     if (aop->size && offset > ( aop->size - 1)) {
1982         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1983                "pic16_aopPut got offset > aop->size");
1984         exit(0);
1985     }
1986
1987     /* will assign value to value */
1988     /* depending on where it is ofcourse */
1989     switch (aop->type) {
1990     case AOP_DIR:
1991       if (offset) {
1992         sprintf(d,"(%s + %d)",
1993                 aop->aopu.aop_dir,offset);
1994         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1995
1996       } else
1997             sprintf(d,"%s",aop->aopu.aop_dir);
1998         
1999         if (strcmp(d,s)) {
2000           DEBUGpic16_emitcode(";","%d",__LINE__);
2001           if(strcmp(s,"W"))
2002             pic16_emitcode("movf","%s,w",s);
2003           pic16_emitcode("movwf","%s",d);
2004
2005           if(strcmp(s,"W")) {
2006             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2007             if(offset >= aop->size) {
2008               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2009               break;
2010             } else
2011               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2012           }
2013
2014           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2015
2016
2017         }
2018         break;
2019         
2020     case AOP_REG:
2021       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2022         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2023           /*
2024             if (*s == '@'           ||
2025                 strcmp(s,"r0") == 0 ||
2026                 strcmp(s,"r1") == 0 ||
2027                 strcmp(s,"r2") == 0 ||
2028                 strcmp(s,"r3") == 0 ||
2029                 strcmp(s,"r4") == 0 ||
2030                 strcmp(s,"r5") == 0 ||
2031                 strcmp(s,"r6") == 0 || 
2032                 strcmp(s,"r7") == 0 )
2033                 pic16_emitcode("mov","%s,%s  ; %d",
2034                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2035             else
2036           */
2037
2038           if(strcmp(s,"W")==0 )
2039             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2040
2041           pic16_emitcode("movwf","%s",
2042                    aop->aopu.aop_reg[offset]->name);
2043
2044           if(strcmp(s,zero)==0) {
2045             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2046
2047           } else if(strcmp(s,"W")==0) {
2048             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2049             pcop->type = PO_GPR_REGISTER;
2050
2051             PCOR(pcop)->rIdx = -1;
2052             PCOR(pcop)->r = NULL;
2053
2054             DEBUGpic16_emitcode(";","%d",__LINE__);
2055             pcop->name = Safe_strdup(s);
2056             pic16_emitpcode(POC_MOVFW,pcop);
2057             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2058           } else if(strcmp(s,one)==0) {
2059             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2060             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2061           } else {
2062             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2063           }
2064         }
2065         break;
2066         
2067     case AOP_DPTR:
2068     case AOP_DPTR2:
2069     
2070     if (aop->type == AOP_DPTR2)
2071     {
2072         genSetDPTR(1);
2073     }
2074     
2075         if (aop->code) {
2076             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2077                    "pic16_aopPut writting to code space");
2078             exit(0);
2079         }
2080         
2081         while (offset > aop->coff) {
2082             aop->coff++;
2083             pic16_emitcode ("inc","dptr");
2084         }
2085         
2086         while (offset < aop->coff) {
2087             aop->coff-- ;
2088             pic16_emitcode("lcall","__decdptr");
2089         }
2090         
2091         aop->coff = offset;
2092         
2093         /* if not in accumulater */
2094         MOVA(s);        
2095         
2096         pic16_emitcode ("movx","@dptr,a");
2097         
2098     if (aop->type == AOP_DPTR2)
2099     {
2100         genSetDPTR(0);
2101     }
2102         break;
2103         
2104     case AOP_R0:
2105     case AOP_R1:
2106         while (offset > aop->coff) {
2107             aop->coff++;
2108             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2109         }
2110         while (offset < aop->coff) {
2111             aop->coff-- ;
2112             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2113         }
2114         aop->coff = offset;
2115         
2116         if (aop->paged) {
2117             MOVA(s);           
2118             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2119             
2120         } else
2121             if (*s == '@') {
2122                 MOVA(s);
2123                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2124             } else
2125                 if (strcmp(s,"r0") == 0 ||
2126                     strcmp(s,"r1") == 0 ||
2127                     strcmp(s,"r2") == 0 ||
2128                     strcmp(s,"r3") == 0 ||
2129                     strcmp(s,"r4") == 0 ||
2130                     strcmp(s,"r5") == 0 ||
2131                     strcmp(s,"r6") == 0 || 
2132                     strcmp(s,"r7") == 0 ) {
2133                     char buffer[10];
2134                     sprintf(buffer,"a%s",s);
2135                     pic16_emitcode("mov","@%s,%s",
2136                              aop->aopu.aop_ptr->name,buffer);
2137                 } else
2138                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2139         
2140         break;
2141         
2142     case AOP_STK:
2143         if (strcmp(s,"a") == 0)
2144             pic16_emitcode("push","acc");
2145         else
2146             pic16_emitcode("push","%s",s);
2147         
2148         break;
2149         
2150     case AOP_CRY:
2151         /* if bit variable */
2152         if (!aop->aopu.aop_dir) {
2153             pic16_emitcode("clr","a");
2154             pic16_emitcode("rlc","a");
2155         } else {
2156             if (s == zero) 
2157                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2158             else
2159                 if (s == one)
2160                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2161                 else
2162                     if (!strcmp(s,"c"))
2163                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2164                     else {
2165                         lbl = newiTempLabel(NULL);
2166                         
2167                         if (strcmp(s,"a")) {
2168                             MOVA(s);
2169                         }
2170                         pic16_emitcode("clr","c");
2171                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2172                         pic16_emitcode("cpl","c");
2173                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2174                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2175                     }
2176         }
2177         break;
2178         
2179     case AOP_STR:
2180         aop->coff = offset;
2181         if (strcmp(aop->aopu.aop_str[offset],s))
2182             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2183         break;
2184         
2185     case AOP_ACC:
2186         aop->coff = offset;
2187         if (!offset && (strcmp(s,"acc") == 0))
2188             break;
2189         
2190         if (strcmp(aop->aopu.aop_str[offset],s))
2191             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2192         break;
2193
2194     default :
2195         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2196 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2197 //             "pic16_aopPut got unsupported aop->type");
2198 //      exit(0);    
2199     }    
2200
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2205 /*-----------------------------------------------------------------*/
2206 static void mov2w (asmop *aop, int offset)
2207 {
2208   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2209
2210   if(is_LitAOp(aop))
2211     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2212   else
2213     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2214 }
2215
2216 static void mov2f(asmop *dst, asmop *src, int offset)
2217 {
2218   if(is_LitAOp(src)) {
2219     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2220     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2221   } else {
2222     if(pic16_sameRegsOfs(src, dst, offset))return;
2223     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2224                       pic16_popGet(dst, offset)));
2225   }
2226 }
2227
2228 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2229 {
2230   if(is_LitAOp(src)) {
2231     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2232     pic16_emitpcode(POC_MOVWF, dst);
2233   } else {
2234     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2235   }
2236 }
2237
2238
2239 /* push pcop into stack */
2240 void pic16_pushpCodeOp(pCodeOp *pcop)
2241 {
2242 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2243         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2244 }
2245
2246 /* pop pcop from stack */
2247 void pic16_poppCodeOp(pCodeOp *pcop)
2248 {
2249         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2250 }
2251
2252
2253 /*-----------------------------------------------------------------*/
2254 /* pushw - pushes wreg to stack                                    */
2255 /*-----------------------------------------------------------------*/
2256 void pushw(void)
2257 {
2258         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2259         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2260 }
2261
2262                 
2263 /*-----------------------------------------------------------------*/
2264 /* pushaop - pushes aop to stack                                   */
2265 /*-----------------------------------------------------------------*/
2266 void pushaop(asmop *aop, int offset)
2267 {
2268         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2269         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* popaop - pops aop from stack                                    */
2274 /*-----------------------------------------------------------------*/
2275 void popaop(asmop *aop, int offset)
2276 {
2277         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2278         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2279 }
2280
2281 void popaopidx(asmop *aop, int offset, int index)
2282 {
2283   int ofs=1;
2284
2285         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2286
2287         if(STACK_MODEL_LARGE)ofs++;
2288
2289         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2290         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2291 }
2292
2293 /*-----------------------------------------------------------------*/
2294 /* reAdjustPreg - points a register back to where it should        */
2295 /*-----------------------------------------------------------------*/
2296 static void reAdjustPreg (asmop *aop)
2297 {
2298     int size ;
2299
2300     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2301     aop->coff = 0;
2302     if ((size = aop->size) <= 1)
2303         return ;
2304     size-- ;
2305     switch (aop->type) {
2306         case AOP_R0 :
2307         case AOP_R1 :
2308             while (size--)
2309                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2310             break;          
2311         case AOP_DPTR :
2312         case AOP_DPTR2:
2313             if (aop->type == AOP_DPTR2)
2314             {
2315                 genSetDPTR(1);
2316             } 
2317             while (size--)
2318             {
2319                 pic16_emitcode("lcall","__decdptr");
2320             }
2321                 
2322             if (aop->type == AOP_DPTR2)
2323             {
2324                 genSetDPTR(0);
2325             }                
2326             break;  
2327
2328     }   
2329
2330 }
2331
2332
2333 #if 0
2334 /*-----------------------------------------------------------------*/
2335 /* opIsGptr: returns non-zero if the passed operand is             */   
2336 /* a generic pointer type.                                         */
2337 /*-----------------------------------------------------------------*/ 
2338 static int opIsGptr(operand *op)
2339 {
2340     sym_link *type = operandType(op);
2341     
2342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2343     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2344     {
2345         return 1;
2346     }
2347     return 0;        
2348 }
2349 #endif
2350
2351 /*-----------------------------------------------------------------*/
2352 /* pic16_getDataSize - get the operand data size                         */
2353 /*-----------------------------------------------------------------*/
2354 int pic16_getDataSize(operand *op)
2355 {
2356     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2357
2358
2359     return AOP_SIZE(op);
2360
2361     // tsd- in the pic port, the genptr size is 1, so this code here
2362     // fails. ( in the 8051 port, the size was 4).
2363 #if 0
2364     int size;
2365     size = AOP_SIZE(op);
2366     if (size == GPTRSIZE)
2367     {
2368         sym_link *type = operandType(op);
2369         if (IS_GENPTR(type))
2370         {
2371             /* generic pointer; arithmetic operations
2372              * should ignore the high byte (pointer type).
2373              */
2374             size--;
2375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2376         }
2377     }
2378     return size;
2379 #endif
2380 }
2381
2382 /*-----------------------------------------------------------------*/
2383 /* pic16_outAcc - output Acc                                             */
2384 /*-----------------------------------------------------------------*/
2385 void pic16_outAcc(operand *result)
2386 {
2387   int size,offset;
2388   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2389   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2390
2391
2392   size = pic16_getDataSize(result);
2393   if(size){
2394     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2395     size--;
2396     offset = 1;
2397     /* unsigned or positive */
2398     while(size--)
2399       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2400   }
2401
2402 }
2403
2404 /*-----------------------------------------------------------------*/
2405 /* pic16_outBitC - output a bit C                                  */
2406 /*                 Move to result the value of Carry flag -- VR    */
2407 /*-----------------------------------------------------------------*/
2408 void pic16_outBitC(operand *result)
2409 {
2410   int i;
2411
2412     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2413     /* if the result is bit */
2414     if (AOP_TYPE(result) == AOP_CRY) {
2415         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2416         pic16_aopPut(AOP(result),"c",0);
2417     } else {
2418
2419         i = AOP_SIZE(result);
2420         while(i--) {
2421                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2422         }
2423         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2424         
2425 /*
2426         pic16_emitcode("clr","a  ; %d", __LINE__);
2427         pic16_emitcode("rlc","a");
2428         pic16_outAcc(result);
2429 */
2430     }
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2435 /*-----------------------------------------------------------------*/
2436 void pic16_toBoolean(operand *oper)
2437 {
2438     int size = AOP_SIZE(oper) - 1;
2439     int offset = 1;
2440
2441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2442
2443     if ( AOP_TYPE(oper) != AOP_ACC) {
2444       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2445     }
2446     while (size--) {
2447       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2448     }
2449 }
2450
2451
2452 #if !defined(GEN_Not)
2453 /*-----------------------------------------------------------------*/
2454 /* genNot - generate code for ! operation                          */
2455 /*-----------------------------------------------------------------*/
2456 static void pic16_genNot (iCode *ic)
2457 {
2458   symbol *tlbl;
2459   int size;
2460
2461   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2462   /* assign asmOps to operand & result */
2463   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2464   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2465
2466   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2467   /* if in bit space then a special case */
2468   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2469     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2470       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2471       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2472     } else {
2473       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2474       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2475       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2476     }
2477     goto release;
2478   }
2479
2480   size = AOP_SIZE(IC_LEFT(ic));
2481   if(size == 1) {
2482     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2483     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2484     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2485     goto release;
2486   }
2487   pic16_toBoolean(IC_LEFT(ic));
2488
2489   tlbl = newiTempLabel(NULL);
2490   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2491   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2492   pic16_outBitC(IC_RESULT(ic));
2493
2494  release:    
2495   /* release the aops */
2496   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2497   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2498 }
2499 #endif
2500
2501
2502 #if !defined(GEN_Cpl)
2503 /*-----------------------------------------------------------------*/
2504 /* genCpl - generate code for complement                           */
2505 /*-----------------------------------------------------------------*/
2506 static void pic16_genCpl (iCode *ic)
2507 {
2508     int offset = 0;
2509     int size ;
2510
2511
2512     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2513     /* assign asmOps to operand & result */
2514     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2515     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2516
2517     /* if both are in bit space then 
2518     a special case */
2519     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2520         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2521
2522         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2523         pic16_emitcode("cpl","c"); 
2524         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2525         goto release; 
2526     } 
2527
2528     size = AOP_SIZE(IC_RESULT(ic));
2529     while (size--) {
2530 /*
2531         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2532         MOVA(l);       
2533         pic16_emitcode("cpl","a");
2534         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2535 */
2536         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2537               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2538         } else {
2539                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2540                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2541         }
2542         offset++;
2543
2544     }
2545
2546
2547 release:
2548     /* release the aops */
2549     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2550     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2551 }
2552 #endif
2553
2554 /*-----------------------------------------------------------------*/
2555 /* genUminusFloat - unary minus for floating points                */
2556 /*-----------------------------------------------------------------*/
2557 static void genUminusFloat(operand *op,operand *result)
2558 {
2559     int size ,offset =0 ;
2560     char *l;
2561
2562     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2563     /* for this we just need to flip the 
2564     first it then copy the rest in place */
2565     size = AOP_SIZE(op) - 1;
2566     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2567
2568     MOVA(l);    
2569
2570     pic16_emitcode("cpl","acc.7");
2571     pic16_aopPut(AOP(result),"a",3);    
2572
2573     while(size--) {
2574         pic16_aopPut(AOP(result),
2575                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2576                offset);
2577         offset++;
2578     }          
2579 }
2580
2581 /*-----------------------------------------------------------------*/
2582 /* genUminus - unary minus code generation                         */
2583 /*-----------------------------------------------------------------*/
2584 static void genUminus (iCode *ic)
2585 {
2586   int size, i;
2587   sym_link *optype, *rtype;
2588
2589         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2590         
2591         /* assign asmops */
2592         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2593         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2594
2595         /* if both in bit space then special case */
2596         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2597                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2598
2599                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2600                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2601                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2602                 
2603                 goto release; 
2604         } 
2605
2606         optype = operandType(IC_LEFT(ic));
2607         rtype = operandType(IC_RESULT(ic));
2608
2609         /* if float then do float stuff */
2610         if (IS_FLOAT(optype)) {
2611                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2612                 goto release;
2613         }
2614
2615         /* otherwise subtract from zero by taking the 2's complement */
2616         size = AOP_SIZE(IC_LEFT(ic));
2617
2618         for(i=0; i<size; i++) {
2619                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2620                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2621                 else {
2622                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2623                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2624                 }
2625         }
2626
2627         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2628         for(i=1; i<size; i++) {
2629                 emitSKPNZ;
2630                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2631         }
2632
2633 release:
2634         /* release the aops */
2635         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2636         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2637 }
2638
2639 #if 0
2640 /*-----------------------------------------------------------------*/
2641 /* saveRegisters - will look for a call and save the registers     */
2642 /*-----------------------------------------------------------------*/
2643 static void saveRegisters(iCode *lic) 
2644 {
2645     int i;
2646     iCode *ic;
2647     bitVect *rsave;
2648     sym_link *dtype;
2649
2650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2651     /* look for call */
2652     for (ic = lic ; ic ; ic = ic->next) 
2653         if (ic->op == CALL || ic->op == PCALL)
2654             break;
2655
2656     if (!ic) {
2657         fprintf(stderr,"found parameter push with no function call\n");
2658         return ;
2659     }
2660
2661     /* if the registers have been saved already then
2662     do nothing */
2663     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2664         return ;
2665
2666     /* find the registers in use at this time 
2667     and push them away to safety */
2668     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2669                           ic->rUsed);
2670
2671     ic->regsSaved = 1;
2672     if (options.useXstack) {
2673         if (bitVectBitValue(rsave,R0_IDX))
2674             pic16_emitcode("mov","b,r0");
2675         pic16_emitcode("mov","r0,%s",spname);
2676         for (i = 0 ; i < pic16_nRegs ; i++) {
2677             if (bitVectBitValue(rsave,i)) {
2678                 if (i == R0_IDX)
2679                     pic16_emitcode("mov","a,b");
2680                 else
2681                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2682                 pic16_emitcode("movx","@r0,a");
2683                 pic16_emitcode("inc","r0");
2684             }
2685         }
2686         pic16_emitcode("mov","%s,r0",spname);
2687         if (bitVectBitValue(rsave,R0_IDX))
2688             pic16_emitcode("mov","r0,b");           
2689     }// else
2690     //for (i = 0 ; i < pic16_nRegs ; i++) {
2691     //    if (bitVectBitValue(rsave,i))
2692     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2693     //}
2694
2695     dtype = operandType(IC_LEFT(ic));
2696     if (currFunc && dtype && 
2697         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2698         IFFUNC_ISISR(currFunc->type) &&
2699         !ic->bankSaved) 
2700
2701         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2702
2703 }
2704 /*-----------------------------------------------------------------*/
2705 /* unsaveRegisters - pop the pushed registers                      */
2706 /*-----------------------------------------------------------------*/
2707 static void unsaveRegisters (iCode *ic)
2708 {
2709     int i;
2710     bitVect *rsave;
2711
2712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2713     /* find the registers in use at this time 
2714     and push them away to safety */
2715     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2716                           ic->rUsed);
2717     
2718     if (options.useXstack) {
2719         pic16_emitcode("mov","r0,%s",spname);   
2720         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2721             if (bitVectBitValue(rsave,i)) {
2722                 pic16_emitcode("dec","r0");
2723                 pic16_emitcode("movx","a,@r0");
2724                 if (i == R0_IDX)
2725                     pic16_emitcode("mov","b,a");
2726                 else
2727                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2728             }       
2729
2730         }
2731         pic16_emitcode("mov","%s,r0",spname);
2732         if (bitVectBitValue(rsave,R0_IDX))
2733             pic16_emitcode("mov","r0,b");
2734     } //else
2735     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2736     //    if (bitVectBitValue(rsave,i))
2737     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2738     //}
2739
2740 }  
2741 #endif
2742
2743 #if 0  // patch 14
2744 /*-----------------------------------------------------------------*/
2745 /* pushSide -                                                      */
2746 /*-----------------------------------------------------------------*/
2747 static void pushSide(operand * oper, int size)
2748 {
2749         int offset = 0;
2750     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2751         while (size--) {
2752                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2753                 if (AOP_TYPE(oper) != AOP_REG &&
2754                     AOP_TYPE(oper) != AOP_DIR &&
2755                     strcmp(l,"a") ) {
2756                         pic16_emitcode("mov","a,%s",l);
2757                         pic16_emitcode("push","acc");
2758                 } else
2759                         pic16_emitcode("push","%s",l);
2760         }
2761 }
2762 #endif // patch 14
2763
2764 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2765 {
2766   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2767     pic16_emitpcode(POC_MOVFW, src);
2768     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2769   } else {
2770     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2771         src, pic16_popGet(AOP(op), offset)));
2772   }
2773 }
2774
2775
2776 /*-----------------------------------------------------------------*/
2777 /* assignResultValue - assign results to oper, rescall==1 is       */
2778 /*                     called from genCall() or genPcall()         */
2779 /*-----------------------------------------------------------------*/
2780 static void assignResultValue(operand * oper, int rescall)
2781 {
2782   int size = AOP_SIZE(oper);
2783   int offset=0;
2784   
2785     DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2786     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2787
2788     if(rescall) {
2789       /* assign result from a call/pcall function() */
2790                 
2791       /* function results are stored in a special order,
2792        * see top of file with Function return policy, or manual */
2793
2794       if(size <= 4) {
2795         /* 8-bits, result in WREG */
2796         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2797                         
2798         if(size>1) {
2799           /* 16-bits, result in PRODL:WREG */
2800           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2801         }
2802                         
2803         if(size>2) {
2804           /* 24-bits, result in PRODH:PRODL:WREG */
2805           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2806         }
2807                         
2808         if(size>3) {
2809           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2810           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2811         }
2812       
2813       } else {
2814         /* >32-bits, result on stack, and FSR0 points to beginning.
2815          * Fix stack when done */
2816         /* FIXME FIXME */
2817         while (size--) {
2818 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2819 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2820                 
2821           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2822           GpsuedoStkPtr++;
2823         }
2824                         
2825         /* fix stack */
2826         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2827         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2828         if(STACK_MODEL_LARGE) {
2829           emitSKPNC;
2830           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2831         }
2832       }                 
2833     } else {
2834       int areg = 0;             /* matching argument register */
2835       
2836       debugf("_G.useWreg = %d\n", _G.useWreg);
2837       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2838
2839
2840       /* its called from genReceive (probably) -- VR */
2841       if(!GpsuedoStkPtr && _G.useWreg) {
2842 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2843
2844         /* The last byte in the assignment is in W */
2845         if(areg <= GpsuedoStkPtr) {
2846           size--;
2847           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2848           offset++;
2849         }
2850       }
2851 //      GpsuedoStkPtr++;
2852       _G.stack_lat = AOP_SIZE(oper)-1;
2853
2854       while (size) {
2855         size--;
2856         GpsuedoStkPtr++;
2857         popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2858         offset++;
2859       }
2860     }
2861 }
2862
2863
2864 /*-----------------------------------------------------------------*/
2865 /* genIpush - generate code for pushing this gets a little complex */
2866 /*-----------------------------------------------------------------*/
2867 static void genIpush (iCode *ic)
2868 {
2869 //  int size, offset=0;
2870
2871   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2872
2873
2874   if(ic->parmPush) {
2875     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2876
2877     /* send to stack as normal */
2878     addSet(&_G.sendSet,ic);
2879 //    addSetHead(&_G.sendSet,ic);
2880     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2881   }
2882
2883         
2884 #if 0
2885     int size, offset = 0 ;
2886     char *l;
2887
2888
2889     /* if this is not a parm push : ie. it is spill push 
2890     and spill push is always done on the local stack */
2891     if (!ic->parmPush) {
2892
2893         /* and the item is spilt then do nothing */
2894         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2895             return ;
2896
2897         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2898         size = AOP_SIZE(IC_LEFT(ic));
2899         /* push it on the stack */
2900         while(size--) {
2901             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2902             if (*l == '#') {
2903                 MOVA(l);
2904                 l = "acc";
2905             }
2906             pic16_emitcode("push","%s",l);
2907         }
2908         return ;        
2909     }
2910
2911     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2912 #endif
2913 }
2914
2915 /*-----------------------------------------------------------------*/
2916 /* genIpop - recover the registers: can happen only for spilling   */
2917 /*-----------------------------------------------------------------*/
2918 static void genIpop (iCode *ic)
2919 {
2920   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2921 #if 0
2922     int size,offset ;
2923
2924
2925     /* if the temp was not pushed then */
2926     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2927         return ;
2928
2929     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2930     size = AOP_SIZE(IC_LEFT(ic));
2931     offset = (size-1);
2932     while (size--) 
2933         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2934                                    FALSE,TRUE));
2935
2936     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2937 #endif
2938 }
2939
2940 #if 0
2941 /*-----------------------------------------------------------------*/
2942 /* unsaverbank - restores the resgister bank from stack            */
2943 /*-----------------------------------------------------------------*/
2944 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2945 {
2946   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2947 #if 0
2948     int i;
2949     asmop *aop ;
2950     regs *r = NULL;
2951
2952     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2953     if (popPsw) {
2954         if (options.useXstack) {
2955             aop = newAsmop(0);
2956             r = getFreePtr(ic,&aop,FALSE);
2957             
2958             
2959             pic16_emitcode("mov","%s,_spx",r->name);
2960             pic16_emitcode("movx","a,@%s",r->name);
2961             pic16_emitcode("mov","psw,a");
2962             pic16_emitcode("dec","%s",r->name);
2963             
2964         }else
2965             pic16_emitcode ("pop","psw");
2966     }
2967
2968     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2969         if (options.useXstack) {       
2970             pic16_emitcode("movx","a,@%s",r->name);
2971             //pic16_emitcode("mov","(%s+%d),a",
2972             //       regspic16[i].base,8*bank+regspic16[i].offset);
2973             pic16_emitcode("dec","%s",r->name);
2974
2975         } else 
2976           pic16_emitcode("pop",""); //"(%s+%d)",
2977         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2978     }
2979
2980     if (options.useXstack) {
2981
2982         pic16_emitcode("mov","_spx,%s",r->name);
2983         pic16_freeAsmop(NULL,aop,ic,TRUE);
2984
2985     }
2986 #endif 
2987 }
2988
2989 /*-----------------------------------------------------------------*/
2990 /* saverbank - saves an entire register bank on the stack          */
2991 /*-----------------------------------------------------------------*/
2992 static void saverbank (int bank, iCode *ic, bool pushPsw)
2993 {
2994   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2995 #if 0
2996     int i;
2997     asmop *aop ;
2998     regs *r = NULL;
2999
3000     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3001     if (options.useXstack) {
3002
3003         aop = newAsmop(0);
3004         r = getFreePtr(ic,&aop,FALSE);  
3005         pic16_emitcode("mov","%s,_spx",r->name);
3006
3007     }
3008
3009     for (i = 0 ; i < pic16_nRegs ;i++) {
3010         if (options.useXstack) {
3011             pic16_emitcode("inc","%s",r->name);
3012             //pic16_emitcode("mov","a,(%s+%d)",
3013             //         regspic16[i].base,8*bank+regspic16[i].offset);
3014             pic16_emitcode("movx","@%s,a",r->name);           
3015         } else 
3016           pic16_emitcode("push","");// "(%s+%d)",
3017                      //regspic16[i].base,8*bank+regspic16[i].offset);
3018     }
3019     
3020     if (pushPsw) {
3021         if (options.useXstack) {
3022             pic16_emitcode("mov","a,psw");
3023             pic16_emitcode("movx","@%s,a",r->name);     
3024             pic16_emitcode("inc","%s",r->name);
3025             pic16_emitcode("mov","_spx,%s",r->name);       
3026             pic16_freeAsmop (NULL,aop,ic,TRUE);
3027             
3028         } else
3029             pic16_emitcode("push","psw");
3030         
3031         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3032     }
3033     ic->bankSaved = 1;
3034 #endif
3035 }
3036 #endif  /* 0 */
3037
3038
3039 /*-----------------------------------------------------------------*/
3040 /* genCall - generates a call statement                            */
3041 /*-----------------------------------------------------------------*/
3042 static void genCall (iCode *ic)
3043 {
3044   sym_link *ftype;   
3045   int stackParms=0;
3046   int use_wreg=0;
3047   char *fname;
3048   
3049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3050
3051     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3052     /* if caller saves & we have not saved then */
3053 //    if (!ic->regsSaved)
3054 //      saveRegisters(ic);
3055
3056         /* initialise stackParms for IPUSH pushes */
3057 //      stackParms = psuedoStkPtr;
3058 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3059     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3060
3061 #if 0
3062     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3063 #endif
3064
3065     /* if send set is not empty the assign */
3066     if (_G.sendSet) {
3067       iCode *sic;
3068       int psuedoStkPtr=-1; 
3069 #if USE_WREG_IN_FUNC_PARAMS
3070       int firstTimeThruLoop = 1;
3071 #endif
3072
3073 #if 1
3074         /* reverse sendSet if function is not reentrant */
3075         if(!IFFUNC_ISREENT(ftype))
3076           _G.sendSet = reverseSet(_G.sendSet);
3077 #endif
3078
3079         /* First figure how many parameters are getting passed */
3080
3081 /*      do we really need to know this ? -- VR 
3082         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3083           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3084           psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3085           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3086         }
3087 */
3088
3089
3090 //        stackParms = psuedoStkPtr;
3091         stackParms = 0;
3092         use_wreg = 0;
3093         
3094         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3095           int size;
3096 #if USE_WREG_IN_FUNC_PARAMS
3097           int offset = 0;
3098 #endif
3099             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3100             size = AOP_SIZE(IC_LEFT(sic));
3101
3102             stackParms += size;
3103
3104             /* set the following to 1 to enable passing arguments via WREG */
3105 #if USE_WREG_IN_FUNC_PARAMS
3106             while (size--) {
3107               DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3108                     pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3109               DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3110
3111               if(!firstTimeThruLoop) {
3112                 /* If this is not the first time we've been through the loop
3113                  * then we need to save the parameter in a temporary
3114                  * register. The last byte of the last parameter is
3115                  * passed in W. */
3116
3117                 pushw();
3118 //                --psuedoStkPtr;               // sanity check
3119                 use_wreg = 1;
3120               }
3121                 
3122               firstTimeThruLoop=0;
3123
3124               mov2w (AOP(IC_LEFT(sic)), size);
3125
3126               offset++;
3127             }
3128 #else
3129             /* all arguments are passed via stack */
3130             while (size--) {
3131               DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3132                     pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3133               DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3134
3135               mov2w (AOP(IC_LEFT(sic)), size);
3136               pushw();
3137             }
3138 #endif
3139
3140             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3141           }
3142
3143 #if USE_WREG_IN_FUNC_PARAMS
3144           /* save last parameter to stack if functions has varargs */
3145           if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
3146           else use_wreg = 1;            /* last parameter in WREG */
3147 #endif
3148
3149           _G.stackRegSet = _G.sendSet;
3150           _G.sendSet = NULL;
3151     }
3152
3153     /* make the call */
3154     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3155
3156     GpsuedoStkPtr=0;
3157     /* if we need to assign a result value */
3158     if ((IS_ITEMP(IC_RESULT(ic))
3159           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3160               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3161         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3162
3163       _G.accInUse++;
3164       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3165       _G.accInUse--;
3166
3167       assignResultValue(IC_RESULT(ic), 1);
3168
3169       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3170                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3171                 
3172       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3173     }
3174
3175     if(!stackParms && ic->parmBytes) {
3176       stackParms = ic->parmBytes;
3177     }
3178       
3179     stackParms -= use_wreg;
3180     
3181     if(stackParms>0) {
3182       if(stackParms == 1) {
3183         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3184       } else {
3185         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3186         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3187       }
3188       if(STACK_MODEL_LARGE) {
3189         emitSKPNC;
3190         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3191       }
3192     }
3193
3194 #if 0
3195     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3196 #endif
3197
3198     /* adjust the stack for parameters if required */
3199 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3200
3201 #if 0
3202       /* if register bank was saved then pop them */
3203       if (ic->bankSaved)
3204         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3205
3206       /* if we hade saved some registers then unsave them */
3207       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3208         unsaveRegisters (ic);
3209 #endif
3210 }
3211
3212
3213
3214 /*-----------------------------------------------------------------*/
3215 /* genPcall - generates a call by pointer statement                */
3216 /*            new version, created from genCall - HJD              */
3217 /*-----------------------------------------------------------------*/
3218 static void genPcall (iCode *ic)
3219 {
3220   sym_link *ftype;
3221   int stackParms=0;
3222   int use_wreg=0;
3223   symbol *retlbl = newiTempLabel(NULL);
3224   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3225   
3226     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3227
3228     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3229     
3230     /* if send set is not empty the assign */
3231     if (_G.sendSet) {
3232       iCode *sic;
3233       int psuedoStkPtr=-1; 
3234 #if USE_WREG_IN_FUNC_PARAMS
3235       int firstTimeThruLoop = 1;
3236 #endif
3237
3238       /* For the Pic port, there is no data stack.
3239        * So parameters passed to functions are stored
3240        * in registers. (The pCode optimizer will get
3241        * rid of most of these :). */
3242
3243
3244 #if 1
3245       /* reverse sendSet if function is not reentrant */
3246       if(!IFFUNC_ISREENT(ftype))
3247         _G.sendSet = reverseSet(_G.sendSet);
3248 #endif
3249
3250       /* First figure how many parameters are getting passed */
3251 #if 0
3252       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3253         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3254         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3255         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3256       }
3257 #endif
3258
3259 //      stackParms = psuedoStkPtr;
3260       stackParms = 0;
3261
3262       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3263         int size;
3264 #if USE_WREG_IN_FUNC_PARAMS
3265         int offset = 0;
3266 #endif
3267
3268           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3269           size = AOP_SIZE(IC_LEFT(sic));
3270           stackParms += size;
3271
3272 #if USE_WREG_IN_FUNC_PARAMS
3273           while (size--) {
3274             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3275             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3276             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3277
3278             if(!firstTimeThruLoop) {
3279               /* If this is not the first time we've been through the loop
3280                * then we need to save the parameter in a temporary
3281                * register. The last byte of the last parameter is
3282                * passed in W. */
3283
3284               pushw();
3285               --psuedoStkPtr;           // sanity check
3286             }
3287                         
3288             firstTimeThruLoop=0;
3289
3290             mov2w (AOP(IC_LEFT(sic)), size);
3291             use_wreg = 1;
3292
3293             offset++;
3294           }
3295 #else
3296           while (size--) {
3297             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3298             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3299             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3300
3301             mov2w (AOP(IC_LEFT(sic)), size);
3302             pushw();
3303           }
3304 #endif
3305
3306           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3307       }
3308
3309 #if USE_WREG_IN_FUNC_PARAMS
3310       if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
3311       else use_wreg = 1;                /* last parameter in WREG */
3312 #endif
3313
3314       _G.stackRegSet = _G.sendSet;
3315       _G.sendSet = NULL;
3316     }
3317
3318     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3319
3320     // push return address
3321     // push $ on return stack, then replace with retlbl
3322
3323     pic16_emitpcodeNULLop(POC_PUSH);
3324
3325     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3326     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3327     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3328     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3329     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3330     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3331
3332     /* make the call by writing the pointer into pc */
3333     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3334     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3335
3336     // note: MOVFF to PCL not allowed
3337     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3338     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3339
3340
3341     /* return address is here: (X) */
3342     pic16_emitpLabelFORCE(retlbl->key);
3343
3344     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3345
3346     GpsuedoStkPtr=0;
3347     /* if we need assign a result value */
3348     if ((IS_ITEMP(IC_RESULT(ic))
3349           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3350               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3351         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3352
3353       _G.accInUse++;
3354       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3355       _G.accInUse--;
3356
3357       assignResultValue(IC_RESULT(ic), 1);
3358
3359       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3360               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3361                 
3362       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3363     }
3364
3365     stackParms -= use_wreg;
3366     
3367     if(stackParms>0) {
3368       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3369       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3370       if(STACK_MODEL_LARGE) {
3371         /* this implies that stackParms < 256 !!! -- VR */
3372         emitSKPNC;
3373         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3374       }
3375     }
3376 }
3377
3378 /*-----------------------------------------------------------------*/
3379 /* resultRemat - result  is rematerializable                       */
3380 /*-----------------------------------------------------------------*/
3381 static int resultRemat (iCode *ic)
3382 {
3383   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3384   if (SKIP_IC(ic) || ic->op == IFX)
3385     return 0;
3386
3387   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3388     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3389     if (sym->remat && !POINTER_SET(ic)) 
3390       return 1;
3391   }
3392
3393   return 0;
3394 }
3395
3396 #if defined(__BORLANDC__) || defined(_MSC_VER)
3397 #define STRCASECMP stricmp
3398 #else
3399 #define STRCASECMP strcasecmp
3400 #endif
3401
3402 #if 0
3403 /*-----------------------------------------------------------------*/
3404 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3405 /*-----------------------------------------------------------------*/
3406 static bool inExcludeList(char *s)
3407 {
3408   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3409     int i =0;
3410     
3411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3412     if (options.excludeRegs[i] &&
3413     STRCASECMP(options.excludeRegs[i],"none") == 0)
3414         return FALSE ;
3415
3416     for ( i = 0 ; options.excludeRegs[i]; i++) {
3417         if (options.excludeRegs[i] &&
3418         STRCASECMP(s,options.excludeRegs[i]) == 0)
3419             return TRUE;
3420     }
3421     return FALSE ;
3422 }
3423 #endif
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genFunction - generated code for function entry                 */
3427 /*-----------------------------------------------------------------*/
3428 static void genFunction (iCode *ic)
3429 {
3430   symbol *sym;
3431   sym_link *ftype;
3432   
3433     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3434
3435     pic16_labelOffset += (max_key+4);
3436     max_key=0;
3437     GpsuedoStkPtr=0;
3438     _G.nRegsSaved = 0;
3439         
3440     ftype = operandType(IC_LEFT(ic));
3441     sym = OP_SYMBOL(IC_LEFT(ic));
3442
3443     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3444       /* create an absolute section at the interrupt vector:
3445        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3446       symbol *asym;
3447       char asymname[128];
3448       pBlock *apb;
3449
3450         {
3451           int i, found=-1;
3452
3453             sym = OP_SYMBOL( IC_LEFT(ic));
3454             for(i=0;i<=2;i++) {
3455               if(interrupts[i]->name
3456                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3457                   found = i;
3458                   break;
3459               }
3460             }
3461                         
3462             if(found == -1) {
3463               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3464                             __FILE__, __LINE__, sym->name);
3465               assert( 0 );
3466             }
3467             _G.interruptvector = found;
3468         }
3469
3470         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3471         asym = newSymbol(asymname, 0);
3472
3473         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3474         pic16_addpBlock( apb );
3475
3476         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3477         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3478         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3479                 
3480         /* mark the end of this tiny function */
3481         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3482
3483         {
3484           absSym *abSym;
3485
3486             abSym = Safe_calloc(1, sizeof(absSym));
3487             strcpy(abSym->name, asymname);
3488
3489             switch( _G.interruptvector ) {
3490               case 0: abSym->address = 0x000000; break;
3491               case 1: abSym->address = 0x000008; break;
3492               case 2: abSym->address = 0x000018; break;
3493             }
3494
3495             /* relocate interrupt vectors if needed */
3496             abSym->address += pic16_options.ivt_loc;
3497
3498             addSet(&absSymSet, abSym);
3499         }
3500     }
3501
3502     /* create the function header */
3503     pic16_emitcode(";","-----------------------------------------");
3504     pic16_emitcode(";"," function %s",sym->name);
3505     pic16_emitcode(";","-----------------------------------------");
3506
3507     pic16_emitcode("","%s:",sym->rname);
3508     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3509
3510
3511     {
3512       absSym *ab;
3513
3514         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3515           if(!strcmp(ab->name, sym->rname)) {
3516             pic16_pBlockConvert2Absolute(pb);
3517             break;
3518           }
3519         }
3520     }
3521
3522
3523     if(IFFUNC_ISNAKED(ftype)) {
3524       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3525       return;
3526     }
3527         
3528     /* if critical function then turn interrupts off */
3529     if (IFFUNC_ISCRITICAL(ftype)) {
3530       //pic16_emitcode("clr","ea");
3531     }
3532
3533     _G.fregsUsed = sym->regsUsed;
3534
3535     /* if this is an interrupt service routine then
3536      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3537     if (IFFUNC_ISISR(sym->type)) {
3538         _G.usefastretfie = 1;   /* use shadow registers by default */
3539         
3540         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3541         if(!(_G.interruptvector == 1)) {
3542           /* do not save WREG,STATUS,BSR for high priority interrupts
3543            * because they are stored in the hardware shadow registers already */
3544           _G.usefastretfie = 0;
3545           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3546           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3547           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3548         }
3549
3550         /* these should really be optimized somehow, because not all
3551          * interrupt handlers modify them */
3552         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3553         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3554         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3555         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3556         
3557 //        pic16_pBlockConvert2ISR(pb);
3558                 
3559     }
3560
3561     /* emit code to setup stack frame if user enabled,
3562      * and function is not main() */
3563          
3564     //fprintf(stderr, "function name: %s\n", sym->name);
3565     if(strcmp(sym->name, "main")) {
3566       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3567         /* setup the stack frame */
3568         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3569         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3570         if(STACK_MODEL_LARGE)
3571           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3572       }
3573     }
3574
3575     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3576           && sym->stack) {
3577
3578       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3579
3580       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3581       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3582       emitSKPNC;
3583       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3584     }
3585           
3586 #if USE_WREG_IN_FUNC_PARAMS
3587     if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3588       _G.useWreg = 0;
3589     else _G.useWreg = 1;
3590 #else
3591     _G.useWreg = 0;
3592 #endif
3593
3594     /* if callee-save to be used for this function
3595      * then save the registers being used in this function */
3596 //    if (IFFUNC_CALLEESAVES(sym->type))
3597     {
3598       int i;
3599
3600         /* if any registers used */
3601         if (sym->regsUsed) {
3602           /* save the registers used */
3603           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3604           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3605           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3606             if (bitVectBitValue(sym->regsUsed,i)) {
3607               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3608               _G.nRegsSaved++;
3609
3610               if(!pic16_regWithIdx(i)->wasUsed) {
3611                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3612                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3613                 pic16_regWithIdx(i)->wasUsed = 1;
3614               }
3615             }
3616           }
3617           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3618         }
3619     }
3620         
3621     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3622 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3623 }
3624
3625 /*-----------------------------------------------------------------*/
3626 /* genEndFunction - generates epilogue for functions               */
3627 /*-----------------------------------------------------------------*/
3628 static void genEndFunction (iCode *ic)
3629 {
3630   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3631
3632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3633
3634     if(IFFUNC_ISNAKED(sym->type)) {
3635       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3636       return;
3637     }
3638
3639     _G.stack_lat = 0;
3640
3641     /* add code for ISCRITICAL */
3642     if(IFFUNC_ISCRITICAL(sym->type)) {
3643       /* if critical function, turn on interrupts */
3644       
3645       /* TODO: add code here -- VR */
3646     }
3647     
3648     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3649           && sym->stack) {
3650       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3651       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3652       emitSKPNC;
3653       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3654     }
3655
3656     /* now we need to restore the registers */
3657     /* if any registers used */
3658     if (sym->regsUsed) {
3659       int i;
3660
3661         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3662         /* restore registers used */
3663         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3664         for ( i = sym->regsUsed->size; i >= 0; i--) {
3665           if (bitVectBitValue(sym->regsUsed,i)) {
3666             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3667             _G.nRegsSaved--;
3668           }
3669         }
3670         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3671
3672     }
3673
3674     if(strcmp(sym->name, "main")) {
3675       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3676         /* restore stack frame */
3677         if(STACK_MODEL_LARGE)
3678           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3679         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3680       }
3681     }
3682
3683     _G.useWreg = 0;
3684
3685     if (IFFUNC_ISISR(sym->type)) {
3686       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3687       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3688       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3689       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3690
3691       if(!(_G.interruptvector == 1)) {
3692         /* do not restore interrupt vector for WREG,STATUS,BSR
3693          * for high priority interrupt, see genFunction */
3694         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3695         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3696         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3697       }
3698       _G.interruptvector = 0;           /* sanity check */
3699
3700
3701       /* if debug then send end of function */
3702 /*      if (options.debug && currFunc)  */
3703       if (currFunc) {
3704         debugFile->writeEndFunction (currFunc, ic, 1);
3705       }
3706         
3707       if(_G.usefastretfie)
3708         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3709       else
3710         pic16_emitpcodeNULLop(POC_RETFIE);
3711
3712       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3713       
3714       _G.usefastretfie = 0;
3715       return;
3716     }
3717
3718     if (IFFUNC_ISCRITICAL(sym->type)) {
3719       pic16_emitcode("setb","ea");
3720     }
3721
3722     /* if debug then send end of function */
3723     if (currFunc) {
3724       debugFile->writeEndFunction (currFunc, ic, 1);
3725     }
3726
3727     /* insert code to restore stack frame, if user enabled it
3728      * and function is not main() */
3729          
3730
3731     pic16_emitpcodeNULLop(POC_RETURN);
3732
3733     /* Mark the end of a function */
3734     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3735 }
3736
3737
3738 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3739 {
3740   if(is_LitOp(op)) {
3741     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3742     if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3743   } else {
3744     if(dest->type == PO_WREG && (offset == 0)) {
3745       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3746       return;
3747     }
3748     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3749   }
3750 }
3751
3752 /*-----------------------------------------------------------------*/
3753 /* genRet - generate code for return statement                     */
3754 /*-----------------------------------------------------------------*/
3755 static void genRet (iCode *ic)
3756 {
3757   int size;
3758   operand *left;
3759
3760         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3761         /* if we have no return value then
3762          * just generate the "ret" */
3763         
3764         if (!IC_LEFT(ic)) 
3765                 goto jumpret;       
3766     
3767         /* we have something to return then
3768          * move the return value into place */
3769         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3770         size = AOP_SIZE(IC_LEFT(ic));
3771
3772         if(size <= 4) {
3773                 if(size>3) {
3774                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3775 //                      pic16_emitpcode(POC_MOVFF,
3776 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3777                 }
3778                 if(size>2) {
3779                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3780 //                      pic16_emitpcode(POC_MOVFF,
3781 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3782                 }
3783                 if(size>1) {
3784                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3785 //                      pic16_emitpcode(POC_MOVFF,
3786 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3787                 }
3788
3789 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3790
3791                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3792 //              pic16_emitpcode(POC_MOVFF,
3793 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3794
3795         } else {
3796                 /* >32-bits, setup stack and FSR0 */
3797                 while (size--) {
3798 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3799 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3800
3801                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3802
3803 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3804                         GpsuedoStkPtr++;
3805                 }
3806                         
3807                 /* setup FSR0 */
3808                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3809                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3810
3811                 if(STACK_MODEL_LARGE) {
3812                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3813                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3814                 } else {
3815                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3816                 }
3817         }
3818                                 
3819 #if 0
3820         /* old code, left here for reference -- VR */    
3821         while (size--) {
3822           char *l ;
3823
3824                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3825                         /* #NOCHANGE */
3826                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3827                         pic16_emitpcomment("push %s",l);
3828                         pushed++;
3829                 } else {
3830                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3831                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3832                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3833                         
3834                         if (strcmp(fReturn[offset],l)) {
3835                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3836                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3837                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3838                                 } else {
3839                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3840                                 }
3841                                 
3842                                 if(size) {
3843                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3844                                 }
3845                                 offset++;
3846                         }
3847                 }
3848         }    
3849
3850         if (pushed) {
3851                 while(pushed) {
3852                         pushed--;
3853                         if (strcmp(fReturn[pushed],"a"))
3854                                 pic16_emitcode("pop",fReturn[pushed]);
3855                         else
3856                                 pic16_emitcode("pop","acc");
3857                 }
3858         }
3859 #endif
3860
3861
3862         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3863     
3864 jumpret:
3865         /* generate a jump to the return label
3866          * if the next is not the return statement */
3867         if (!(ic->next && ic->next->op == LABEL
3868                 && IC_LABEL(ic->next) == returnLabel)) {
3869         
3870                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3871                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3872         }
3873 }
3874
3875 /*-----------------------------------------------------------------*/
3876 /* genLabel - generates a label                                    */
3877 /*-----------------------------------------------------------------*/
3878 static void genLabel (iCode *ic)
3879 {
3880
3881
3882     /* special case never generate */
3883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3884     if (IC_LABEL(ic) == entryLabel)
3885         return ;
3886
3887     pic16_emitpLabel(IC_LABEL(ic)->key);
3888     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3889 }
3890
3891 /*-----------------------------------------------------------------*/
3892 /* genGoto - generates a goto                                      */
3893 /*-----------------------------------------------------------------*/
3894 //tsd
3895 static void genGoto (iCode *ic)
3896 {
3897   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3898   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3899 }
3900
3901
3902 /*-----------------------------------------------------------------*/
3903 /* genMultbits :- multiplication of bits                           */
3904 /*-----------------------------------------------------------------*/
3905 static void genMultbits (operand *left, 
3906                          operand *right, 
3907                          operand *result)
3908 {
3909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3910
3911   if(!pic16_sameRegs(AOP(result),AOP(right)))
3912     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3913
3914   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3915   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3916   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3917
3918 }
3919
3920
3921 /*-----------------------------------------------------------------*/
3922 /* genMultOneByte : 8 bit multiplication & division                */
3923 /*-----------------------------------------------------------------*/
3924 static void genMultOneByte (operand *left,
3925                             operand *right,
3926                             operand *result)
3927 {
3928
3929   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3930   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3931   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3932
3933   /* (if two literals, the value is computed before) */
3934   /* if one literal, literal on the right */
3935   if (AOP_TYPE(left) == AOP_LIT){
3936     operand *t = right;
3937     right = left;
3938     left = t;
3939   }
3940
3941         /* size is already checked in genMult == 1 */
3942 //      size = AOP_SIZE(result);
3943
3944         if (AOP_TYPE(right) == AOP_LIT){
3945                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3946                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3947                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3948                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3949         } else {
3950                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3951                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3952                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3953                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3954         }
3955         
3956         pic16_genMult8X8_8 (left, right,result);
3957 }
3958
3959 /*-----------------------------------------------------------------*/
3960 /* genMultOneWord : 16 bit multiplication                          */
3961 /*-----------------------------------------------------------------*/
3962 static void genMultOneWord (operand *left,
3963                             operand *right,
3964                             operand *result)
3965 {
3966
3967         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3968         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3969         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3970
3971         /* (if two literals, the value is computed before)
3972          * if one literal, literal on the right */
3973         if (AOP_TYPE(left) == AOP_LIT){
3974           operand *t = right;
3975                 right = left;
3976                 left = t;
3977         }
3978
3979         /* size is checked already == 2 */
3980 //      size = AOP_SIZE(result);
3981
3982         if (AOP_TYPE(right) == AOP_LIT) {
3983                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3984                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3985                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3986                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3987         } else {
3988                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3989                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3990                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3991                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3992         }
3993         
3994         pic16_genMult16X16_16(left, right,result);
3995 }
3996
3997 /*-----------------------------------------------------------------*/
3998 /* genMultOneLong : 32 bit multiplication                          */
3999 /*-----------------------------------------------------------------*/
4000 static void genMultOneLong (operand *left,
4001                             operand *right,
4002                             operand *result)
4003 {
4004
4005         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4006         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4007         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4008
4009         /* (if two literals, the value is computed before)
4010          * if one literal, literal on the right */
4011         if (AOP_TYPE(left) == AOP_LIT){
4012           operand *t = right;
4013                 right = left;
4014                 left = t;
4015         }
4016
4017         /* size is checked already == 4 */
4018 //      size = AOP_SIZE(result);
4019
4020         if (AOP_TYPE(right) == AOP_LIT) {
4021                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4022                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4023                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4024                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4025         } else {
4026                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4027                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4028                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4029                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4030         }
4031         
4032         pic16_genMult32X32_32(left, right,result);
4033 }
4034
4035
4036
4037 /*-----------------------------------------------------------------*/
4038 /* genMult - generates code for multiplication                     */
4039 /*-----------------------------------------------------------------*/
4040 static void genMult (iCode *ic)
4041 {
4042   operand *left = IC_LEFT(ic);
4043   operand *right = IC_RIGHT(ic);
4044   operand *result= IC_RESULT(ic);   
4045
4046         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4047         /* assign the amsops */
4048         pic16_aopOp (left,ic,FALSE);
4049         pic16_aopOp (right,ic,FALSE);
4050         pic16_aopOp (result,ic,TRUE);
4051
4052         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4053
4054         /* special cases first *
4055         * both are bits */
4056         if (AOP_TYPE(left) == AOP_CRY
4057                 && AOP_TYPE(right)== AOP_CRY) {
4058                 genMultbits(left,right,result);
4059           goto release ;
4060         }
4061
4062         /* if both are of size == 1 */
4063         if(AOP_SIZE(left) == 1
4064                 && AOP_SIZE(right) == 1) {
4065                 genMultOneByte(left,right,result);
4066           goto release ;
4067         }
4068
4069         /* if both are of size == 2 */
4070         if(AOP_SIZE(left) == 2
4071                 && AOP_SIZE(right) == 2) {
4072                 genMultOneWord(left, right, result);
4073           goto release;
4074         }
4075         
4076         /* if both are of size == 4 */
4077         if(AOP_SIZE(left) == 4
4078                 && AOP_SIZE(right) == 4) {
4079                 genMultOneLong(left, right, result);
4080           goto release;
4081         }
4082         
4083         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4084
4085
4086         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4087         /* should have been converted to function call */
4088         assert(0) ;
4089
4090 release :
4091         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4092         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4093         pic16_freeAsmop(result,NULL,ic,TRUE); 
4094 }
4095
4096 /*-----------------------------------------------------------------*/
4097 /* genDivbits :- division of bits                                  */
4098 /*-----------------------------------------------------------------*/
4099 static void genDivbits (operand *left, 
4100                         operand *right, 
4101                         operand *result)
4102 {
4103
4104     char *l;
4105
4106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4107     /* the result must be bit */    
4108     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4109     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4110
4111     MOVA(l);    
4112
4113     pic16_emitcode("div","ab");
4114     pic16_emitcode("rrc","a");
4115     pic16_aopPut(AOP(result),"c",0);
4116 }
4117
4118 /*-----------------------------------------------------------------*/
4119 /* genDivOneByte : 8 bit division                                  */
4120 /*-----------------------------------------------------------------*/
4121 static void genDivOneByte (operand *left,
4122                            operand *right,
4123                            operand *result)
4124 {
4125     sym_link *opetype = operandType(result);
4126     char *l ;
4127     symbol *lbl ;
4128     int size,offset;
4129
4130         /* result = divident / divisor
4131          * - divident may be a register or a literal,
4132          * - divisor may be a register or a literal,
4133          * so there are 3 cases (literal / literal is optimized
4134          * by the front-end) to handle.
4135          * In addition we must handle signed and unsigned, which
4136          * result in 6 final different cases -- VR */
4137
4138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4139     size = AOP_SIZE(result) - 1;
4140     offset = 1;
4141     /* signed or unsigned */
4142     if (SPEC_USIGN(opetype)) {
4143       pCodeOp *pct1,    /* count */
4144                 *pct2,  /* reste */
4145                 *pct3;  /* temp */
4146       symbol *label1, *label2, *label3;;
4147
4148
4149         /* unsigned is easy */
4150
4151         pct1 = pic16_popGetTempReg(1);
4152         pct2 = pic16_popGetTempReg(1);
4153         pct3 = pic16_popGetTempReg(1);
4154         
4155         label1 = newiTempLabel(NULL);
4156         label2 = newiTempLabel(NULL);
4157         label3 = newiTempLabel(NULL);
4158
4159         /* the following algorithm is extracted from divuint.c */
4160
4161         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4162         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4163         
4164         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4165
4166         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4167         
4168         pic16_emitpLabel(label1->key);
4169         
4170         emitCLRC;
4171         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4172
4173
4174         emitCLRC;
4175         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4176         
4177
4178         emitSKPNC;
4179         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4180         
4181         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4182         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4183         
4184         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4185         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4186         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4187         
4188         pic16_emitpLabel( label3->key );
4189         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4190         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4191         
4192         
4193
4194         pic16_emitpLabel(label2->key);
4195         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4196         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4197         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4198         
4199         /* result is in wreg */
4200         if(AOP_TYPE(result) != AOP_ACC)
4201                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4202
4203         pic16_popReleaseTempReg( pct3, 1);
4204         pic16_popReleaseTempReg( pct2, 1);
4205         pic16_popReleaseTempReg( pct1, 1);
4206
4207         return ;
4208     }
4209
4210     /* signed is a little bit more difficult */
4211
4212     /* save the signs of the operands */
4213     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4214     MOVA(l);    
4215     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4216     pic16_emitcode("push","acc"); /* save it on the stack */
4217
4218     /* now sign adjust for both left & right */
4219     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4220     MOVA(l);       
4221     lbl = newiTempLabel(NULL);
4222     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4223     pic16_emitcode("cpl","a");   
4224     pic16_emitcode("inc","a");
4225     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4226     pic16_emitcode("mov","b,a");
4227
4228     /* sign adjust left side */
4229     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4230     MOVA(l);
4231
4232     lbl = newiTempLabel(NULL);
4233     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4234     pic16_emitcode("cpl","a");
4235     pic16_emitcode("inc","a");
4236     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4237
4238     /* now the division */
4239     pic16_emitcode("div","ab");
4240     /* we are interested in the lower order
4241     only */
4242     pic16_emitcode("mov","b,a");
4243     lbl = newiTempLabel(NULL);
4244     pic16_emitcode("pop","acc");   
4245     /* if there was an over flow we don't 
4246     adjust the sign of the result */
4247     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4248     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4249     CLRC;
4250     pic16_emitcode("clr","a");
4251     pic16_emitcode("subb","a,b");
4252     pic16_emitcode("mov","b,a");
4253     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4254
4255     /* now we are done */
4256     pic16_aopPut(AOP(result),"b",0);
4257     if(size > 0){
4258         pic16_emitcode("mov","c,b.7");
4259         pic16_emitcode("subb","a,acc");   
4260     }
4261     while (size--)
4262         pic16_aopPut(AOP(result),"a",offset++);
4263
4264 }
4265
4266 /*-----------------------------------------------------------------*/
4267 /* genDiv - generates code for division                            */
4268 /*-----------------------------------------------------------------*/
4269 static void genDiv (iCode *ic)
4270 {
4271     operand *left = IC_LEFT(ic);
4272     operand *right = IC_RIGHT(ic);
4273     operand *result= IC_RESULT(ic);   
4274
4275
4276         /* Division is a very lengthy algorithm, so it is better
4277          * to call support routines than inlining algorithm.
4278          * Division functions written here just in case someone
4279          * wants to inline and not use the support libraries -- VR */
4280
4281     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4282     /* assign the amsops */
4283     pic16_aopOp (left,ic,FALSE);
4284     pic16_aopOp (right,ic,FALSE);
4285     pic16_aopOp (result,ic,TRUE);
4286
4287     /* special cases first */
4288     /* both are bits */
4289     if (AOP_TYPE(left) == AOP_CRY &&
4290         AOP_TYPE(right)== AOP_CRY) {
4291         genDivbits(left,right,result);
4292         goto release ;
4293     }
4294
4295     /* if both are of size == 1 */
4296     if (AOP_SIZE(left) == 1 &&
4297         AOP_SIZE(right) == 1 ) {
4298         genDivOneByte(left,right,result);
4299         goto release ;
4300     }
4301
4302     /* should have been converted to function call */
4303     assert(0);
4304 release :
4305     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4306     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4307     pic16_freeAsmop(result,NULL,ic,TRUE); 
4308 }
4309
4310 /*-----------------------------------------------------------------*/
4311 /* genModbits :- modulus of bits                                   */
4312 /*-----------------------------------------------------------------*/
4313 static void genModbits (operand *left, 
4314                         operand *right, 
4315                         operand *result)
4316 {
4317
4318     char *l;
4319
4320     /* the result must be bit */    
4321     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4322     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4323
4324     MOVA(l);       
4325
4326     pic16_emitcode("div","ab");
4327     pic16_emitcode("mov","a,b");
4328     pic16_emitcode("rrc","a");
4329     pic16_aopPut(AOP(result),"c",0);
4330 }
4331
4332 /*-----------------------------------------------------------------*/
4333 /* genModOneByte : 8 bit modulus                                   */
4334 /*-----------------------------------------------------------------*/
4335 static void genModOneByte (operand *left,
4336                            operand *right,
4337                            operand *result)
4338 {
4339     sym_link *opetype = operandType(result);
4340     char *l ;
4341     symbol *lbl ;
4342
4343     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4344     /* signed or unsigned */
4345     if (SPEC_USIGN(opetype)) {
4346         /* unsigned is easy */
4347         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4348         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4349         MOVA(l);    
4350         pic16_emitcode("div","ab");
4351         pic16_aopPut(AOP(result),"b",0);
4352         return ;
4353     }
4354
4355     /* signed is a little bit more difficult */
4356
4357     /* save the signs of the operands */
4358     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4359     MOVA(l);
4360
4361     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4362     pic16_emitcode("push","acc"); /* save it on the stack */
4363
4364     /* now sign adjust for both left & right */
4365     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4366     MOVA(l);
4367
4368     lbl = newiTempLabel(NULL);
4369     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4370     pic16_emitcode("cpl","a");   
4371     pic16_emitcode("inc","a");
4372     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4373     pic16_emitcode("mov","b,a"); 
4374
4375     /* sign adjust left side */
4376     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4377     MOVA(l);
4378
4379     lbl = newiTempLabel(NULL);
4380     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4381     pic16_emitcode("cpl","a");   
4382     pic16_emitcode("inc","a");
4383     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4384
4385     /* now the multiplication */
4386     pic16_emitcode("div","ab");
4387     /* we are interested in the lower order
4388     only */
4389     lbl = newiTempLabel(NULL);
4390     pic16_emitcode("pop","acc");   
4391     /* if there was an over flow we don't 
4392     adjust the sign of the result */
4393     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4394     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4395     CLRC ;
4396     pic16_emitcode("clr","a");
4397     pic16_emitcode("subb","a,b");
4398     pic16_emitcode("mov","b,a");
4399     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4400
4401     /* now we are done */
4402     pic16_aopPut(AOP(result),"b",0);
4403
4404 }
4405
4406 /*-----------------------------------------------------------------*/
4407 /* genMod - generates code for division                            */
4408 /*-----------------------------------------------------------------*/
4409 static void genMod (iCode *ic)
4410 {
4411     operand *left = IC_LEFT(ic);
4412     operand *right = IC_RIGHT(ic);
4413     operand *result= IC_RESULT(ic);  
4414
4415     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4416     /* assign the amsops */
4417     pic16_aopOp (left,ic,FALSE);
4418     pic16_aopOp (right,ic,FALSE);
4419     pic16_aopOp (result,ic,TRUE);
4420
4421     /* special cases first */
4422     /* both are bits */
4423     if (AOP_TYPE(left) == AOP_CRY &&
4424         AOP_TYPE(right)== AOP_CRY) {
4425         genModbits(left,right,result);
4426         goto release ;
4427     }
4428
4429     /* if both are of size == 1 */
4430     if (AOP_SIZE(left) == 1 &&
4431         AOP_SIZE(right) == 1 ) {
4432         genModOneByte(left,right,result);
4433         goto release ;
4434     }
4435
4436     /* should have been converted to function call */
4437     assert(0);
4438
4439 release :
4440     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4442     pic16_freeAsmop(result,NULL,ic,TRUE); 
4443 }
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genIfxJump :- will create a jump depending on the ifx           */
4447 /*-----------------------------------------------------------------*/
4448 /*
4449   note: May need to add parameter to indicate when a variable is in bit space.
4450 */
4451 static void genIfxJump (iCode *ic, char *jval)
4452 {
4453
4454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4455     /* if true label then we jump if condition
4456     supplied is true */
4457     if ( IC_TRUE(ic) ) {
4458
4459         if(strcmp(jval,"a") == 0)
4460           emitSKPZ;
4461         else if (strcmp(jval,"c") == 0)
4462           emitSKPC;
4463         else {
4464           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4465           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4466         }
4467
4468         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4469         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4470
4471     }
4472     else {
4473         /* false label is present */
4474         if(strcmp(jval,"a") == 0)
4475           emitSKPNZ;
4476         else if (strcmp(jval,"c") == 0)
4477           emitSKPNC;
4478         else {
4479           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4480           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4481         }
4482
4483         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4484         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4485
4486     }
4487
4488
4489     /* mark the icode as generated */
4490     ic->generated = 1;
4491 }
4492
4493 #if 0
4494 // not needed ATM
4495
4496 /*-----------------------------------------------------------------*/
4497 /* genSkip                                                         */
4498 /*-----------------------------------------------------------------*/
4499 static void genSkip(iCode *ifx,int status_bit)
4500 {
4501   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4502   if(!ifx)
4503     return;
4504
4505   if ( IC_TRUE(ifx) ) {
4506     switch(status_bit) {
4507     case 'z':
4508       emitSKPNZ;
4509       break;
4510
4511     case 'c':
4512       emitSKPNC;
4513       break;
4514
4515     case 'd':
4516       emitSKPDC;
4517       break;
4518
4519     }
4520
4521     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4522     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4523
4524   } else {
4525
4526     switch(status_bit) {
4527
4528     case 'z':
4529       emitSKPZ;
4530       break;
4531
4532     case 'c':
4533       emitSKPC;
4534       break;
4535
4536     case 'd':
4537       emitSKPDC;
4538       break;
4539     }
4540     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4541     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4542
4543   }
4544
4545 }
4546 #endif
4547
4548 /*-----------------------------------------------------------------*/
4549 /* genSkipc                                                        */
4550 /*-----------------------------------------------------------------*/
4551 static void genSkipc(resolvedIfx *rifx)
4552 {
4553   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4554   
4555   if(!rifx)
4556     return;
4557
4558   if(rifx->condition)
4559     emitSKPC;
4560   else
4561     emitSKPNC;
4562
4563   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4564   rifx->generated = 1;
4565 }
4566
4567 /*-----------------------------------------------------------------*/
4568 /* genSkipz2                                                       */
4569 /*-----------------------------------------------------------------*/
4570 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4571 {
4572   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4573   
4574   if(!rifx)
4575     return;
4576
4577   if( (rifx->condition ^ invert_condition) & 1)
4578     emitSKPZ;
4579   else
4580     emitSKPNZ;
4581
4582   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4583   rifx->generated = 1;
4584 }
4585
4586 #if 0
4587 /*-----------------------------------------------------------------*/
4588 /* genSkipz                                                        */
4589 /*-----------------------------------------------------------------*/
4590 static void genSkipz(iCode *ifx, int condition)
4591 {
4592   if(!ifx)
4593     return;
4594
4595   if(condition)
4596     emitSKPNZ;
4597   else
4598     emitSKPZ;
4599
4600   if ( IC_TRUE(ifx) )
4601     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4602   else
4603     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4604
4605   if ( IC_TRUE(ifx) )
4606     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4607   else
4608     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4609
4610 }
4611 #endif
4612
4613 /*-----------------------------------------------------------------*/
4614 /* genSkipCond                                                     */
4615 /*-----------------------------------------------------------------*/
4616 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4617 {
4618   if(!rifx)
4619     return;
4620
4621   if(rifx->condition)
4622     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4623   else
4624     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4625
4626
4627   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4628   rifx->generated = 1;
4629 }
4630
4631 #if 0
4632 /*-----------------------------------------------------------------*/
4633 /* genChkZeroes :- greater or less than comparison                 */
4634 /*     For each byte in a literal that is zero, inclusive or the   */
4635 /*     the corresponding byte in the operand with W                */
4636 /*     returns true if any of the bytes are zero                   */
4637 /*-----------------------------------------------------------------*/
4638 static int genChkZeroes(operand *op, int lit,  int size)
4639 {
4640
4641   int i;
4642   int flag =1;
4643
4644   while(size--) {
4645     i = (lit >> (size*8)) & 0xff;
4646
4647     if(i==0) {
4648       if(flag) 
4649         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4650       else
4651         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4652       flag = 0;
4653     }
4654   }
4655
4656   return (flag==0);
4657 }
4658 #endif
4659
4660 /*-----------------------------------------------------------------*/
4661 /* genCmp :- greater or less than comparison                       */
4662 /*-----------------------------------------------------------------*/
4663 #if 1
4664 static void genCmp (operand *left,operand *right,
4665                     operand *result, iCode *ifx, int sign)
4666 {
4667   int size; //, offset = 0 ;
4668   unsigned long lit = 0L,i = 0;
4669   resolvedIfx rFalseIfx;
4670   //  resolvedIfx rTrueIfx;
4671   symbol *truelbl;
4672   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4673 /*
4674   if(ifx) {
4675     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4676     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4677   }
4678 */
4679
4680   resolveIfx(&rFalseIfx,ifx);
4681   truelbl  = newiTempLabel(NULL);
4682   size = max(AOP_SIZE(left),AOP_SIZE(right));
4683
4684   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4685
4686 #define _swapp
4687
4688   /* if literal is on the right then swap with left */
4689   if ((AOP_TYPE(right) == AOP_LIT)) {
4690     operand *tmp = right ;
4691     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4692     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4693 #ifdef _swapp
4694
4695     lit = (lit - 1) & mask;
4696     right = left;
4697     left = tmp;
4698     rFalseIfx.condition ^= 1;
4699 #endif
4700
4701   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4702     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4703   }
4704
4705
4706   //if(IC_TRUE(ifx) == NULL)
4707   /* if left & right are bit variables */
4708   if (AOP_TYPE(left) == AOP_CRY &&
4709       AOP_TYPE(right) == AOP_CRY ) {
4710     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4711     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4712   } else {
4713     /* subtract right from left if at the
4714        end the carry flag is set then we know that
4715        left is greater than right */
4716
4717     symbol *lbl  = newiTempLabel(NULL);
4718
4719 #if 0
4720         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4721                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4722 #endif
4723
4724 #ifndef _swapp
4725     if(AOP_TYPE(right) == AOP_LIT) {
4726
4727       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4728
4729       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4730
4731       /* special cases */
4732
4733       if(lit == 0) {
4734
4735         if(sign != 0) 
4736           genSkipCond(&rFalseIfx,left,size-1,7);
4737         else 
4738           /* no need to compare to 0...*/
4739           /* NOTE: this is a de-generate compare that most certainly 
4740            *       creates some dead code. */
4741           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4742
4743         if(ifx) ifx->generated = 1;
4744         return;
4745
4746       }
4747       size--;
4748
4749       if(size == 0) {
4750         //i = (lit >> (size*8)) & 0xff;
4751         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4752         
4753         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4754
4755         i = ((0-lit) & 0xff);
4756         if(sign) {
4757           if( i == 0x81) { 
4758             /* lit is 0x7f, all signed chars are less than
4759              * this except for 0x7f itself */
4760             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4761             genSkipz2(&rFalseIfx,0);
4762           } else {
4763             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4764             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4765             genSkipc(&rFalseIfx);
4766           }
4767
4768         } else {
4769           if(lit == 1) {
4770             genSkipz2(&rFalseIfx,1);
4771           } else {
4772             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4773             genSkipc(&rFalseIfx);
4774           }
4775         }
4776
4777         if(ifx) ifx->generated = 1;
4778         return;
4779       }
4780
4781       /* chars are out of the way. now do ints and longs */
4782
4783
4784       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4785         
4786       /* special cases */
4787
4788       if(sign) {
4789
4790         if(lit == 0) {
4791           genSkipCond(&rFalseIfx,left,size,7);
4792           if(ifx) ifx->generated = 1;
4793           return;
4794         }
4795
4796         if(lit <0x100) {
4797           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4798
4799           //rFalseIfx.condition ^= 1;
4800           //genSkipCond(&rFalseIfx,left,size,7);
4801           //rFalseIfx.condition ^= 1;
4802
4803           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4804           if(rFalseIfx.condition)
4805             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4806           else
4807             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4808
4809           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4810           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4811           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4812
4813           while(size > 1)
4814             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4815
4816           if(rFalseIfx.condition) {
4817             emitSKPZ;
4818             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4819
4820           } else {
4821             emitSKPNZ;
4822           }
4823
4824           genSkipc(&rFalseIfx);
4825           pic16_emitpLabel(truelbl->key);
4826           if(ifx) ifx->generated = 1;
4827           return;
4828
4829         }
4830
4831         if(size == 1) {
4832
4833           if( (lit & 0xff) == 0) {
4834             /* lower byte is zero */
4835             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4836             i = ((lit >> 8) & 0xff) ^0x80;
4837             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4838             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4839             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4840             genSkipc(&rFalseIfx);
4841
4842
4843             if(ifx) ifx->generated = 1;
4844             return;
4845
4846           }
4847         } else {
4848           /* Special cases for signed longs */
4849           if( (lit & 0xffffff) == 0) {
4850             /* lower byte is zero */
4851             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4852             i = ((lit >> 8*3) & 0xff) ^0x80;
4853             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4854             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4855             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4856             genSkipc(&rFalseIfx);
4857
4858
4859             if(ifx) ifx->generated = 1;
4860             return;
4861
4862           }
4863
4864         }
4865
4866
4867         if(lit & (0x80 << (size*8))) {
4868           /* lit is negative */
4869           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4870
4871           //genSkipCond(&rFalseIfx,left,size,7);
4872
4873           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4874
4875           if(rFalseIfx.condition)
4876             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4877           else
4878             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4879
4880
4881         } else {
4882           /* lit is positive */
4883           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4884           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4885           if(rFalseIfx.condition)
4886             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4887           else
4888             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4889
4890         }
4891
4892         /*
4893           This works, but is only good for ints.
4894           It also requires a "known zero" register.
4895           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4896           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4897           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4898           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4899           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4900           genSkipc(&rFalseIfx);
4901
4902           pic16_emitpLabel(truelbl->key);
4903           if(ifx) ifx->generated = 1;
4904           return;
4905         **/
4906           
4907         /* There are no more special cases, so perform a general compare */
4908   
4909         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4910         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4911
4912         while(size--) {
4913
4914           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4915           emitSKPNZ;
4916           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4917         }
4918         //rFalseIfx.condition ^= 1;
4919         genSkipc(&rFalseIfx);
4920
4921         pic16_emitpLabel(truelbl->key);
4922
4923         if(ifx) ifx->generated = 1;
4924         return;
4925
4926
4927       }
4928
4929
4930       /* sign is out of the way. So now do an unsigned compare */
4931       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4932
4933
4934       /* General case - compare to an unsigned literal on the right.*/
4935
4936       i = (lit >> (size*8)) & 0xff;
4937       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4938       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4939       while(size--) {
4940         i = (lit >> (size*8)) & 0xff;
4941
4942         if(i) {
4943           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4944           emitSKPNZ;
4945           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4946         } else {
4947           /* this byte of the lit is zero, 
4948            *if it's not the last then OR in the variable */
4949           if(size)
4950             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4951         }
4952       }
4953
4954
4955       pic16_emitpLabel(lbl->key);
4956 //      pic16_emitpLabel(truelbl->key);
4957       //if(emitFinalCheck)
4958       genSkipc(&rFalseIfx);
4959       if(sign)
4960         pic16_emitpLabel(truelbl->key);
4961
4962       if(ifx) ifx->generated = 1;
4963       return;
4964
4965
4966     }
4967 #endif  // _swapp
4968
4969     if(AOP_TYPE(left) == AOP_LIT) {
4970       //symbol *lbl = newiTempLabel(NULL);
4971
4972       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4973
4974
4975       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4976
4977       /* Special cases */
4978       if((lit == 0) && (sign == 0)){
4979
4980         size--;
4981         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4982         while(size) 
4983           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4984
4985         genSkipz2(&rFalseIfx,0);
4986         if(ifx) ifx->generated = 1;
4987         return;
4988       }
4989
4990       if(size==1) {
4991         /* Special cases */
4992         lit &= 0xff;
4993         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4994           /* degenerate compare can never be true */
4995           if(rFalseIfx.condition == 0)
4996             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4997
4998           if(ifx) ifx->generated = 1;
4999           return;
5000         }
5001
5002         if(sign) {
5003           /* signed comparisons to a literal byte */
5004
5005           int lp1 = (lit+1) & 0xff;
5006
5007           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5008           switch (lp1) {
5009           case 0:
5010             rFalseIfx.condition ^= 1;
5011             genSkipCond(&rFalseIfx,right,0,7);
5012             break;
5013           case 0x7f:
5014             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5015             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5016             genSkipz2(&rFalseIfx,1);
5017             break;
5018           default:
5019             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5020             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5021             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5022             rFalseIfx.condition ^= 1;
5023             genSkipc(&rFalseIfx);
5024             break;
5025           }
5026         } else {
5027           /* unsigned comparisons to a literal byte */
5028
5029           switch(lit & 0xff ) {
5030           case 0:
5031             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5032             genSkipz2(&rFalseIfx,0);
5033             break;
5034           case 0x7f:
5035             rFalseIfx.condition ^= 1;
5036             genSkipCond(&rFalseIfx,right,0,7);
5037             break;
5038
5039           default:
5040             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5041             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5042             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5043             rFalseIfx.condition ^= 1;
5044             if (AOP_TYPE(result) == AOP_CRY)
5045               genSkipc(&rFalseIfx);
5046             else {
5047               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5048               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5049             }         
5050             break;
5051           }
5052         }
5053
5054         if(ifx) ifx->generated = 1;
5055         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5056                 goto check_carry;
5057         return;
5058
5059       } else {
5060
5061         /* Size is greater than 1 */
5062
5063         if(sign) {
5064           int lp1 = lit+1;
5065
5066           size--;
5067
5068           if(lp1 == 0) {
5069             /* this means lit = 0xffffffff, or -1 */
5070
5071
5072             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5073             rFalseIfx.condition ^= 1;
5074             genSkipCond(&rFalseIfx,right,size,7);
5075             if(ifx) ifx->generated = 1;
5076
5077             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5078               goto check_carry;
5079
5080             return;
5081           }
5082
5083           if(lit == 0) {
5084             int s = size;
5085
5086             if(rFalseIfx.condition) {
5087               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5088               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5089             }
5090
5091             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5092             while(size--)
5093               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5094
5095
5096             emitSKPZ;
5097             if(rFalseIfx.condition) {
5098               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5099               pic16_emitpLabel(truelbl->key);
5100             }else {
5101               rFalseIfx.condition ^= 1;
5102               genSkipCond(&rFalseIfx,right,s,7);
5103             }
5104
5105             if(ifx) ifx->generated = 1;
5106
5107             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5108               goto check_carry;
5109
5110             return;
5111           }
5112
5113           if((size == 1) &&  (0 == (lp1&0xff))) {
5114             /* lower byte of signed word is zero */
5115             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5116             i = ((lp1 >> 8) & 0xff) ^0x80;
5117             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5118             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5119             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5120             rFalseIfx.condition ^= 1;
5121             genSkipc(&rFalseIfx);
5122
5123
5124             if(ifx) ifx->generated = 1;
5125
5126             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5127               goto check_carry;
5128
5129             return;
5130           }
5131
5132           if(lit & (0x80 << (size*8))) {
5133             /* Lit is less than zero */
5134             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5135             //rFalseIfx.condition ^= 1;
5136             //genSkipCond(&rFalseIfx,left,size,7);
5137             //rFalseIfx.condition ^= 1;
5138             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5139             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5140
5141             if(rFalseIfx.condition)
5142               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5143             else
5144               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5145
5146
5147           } else {
5148             /* Lit is greater than or equal to zero */
5149             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5150             //rFalseIfx.condition ^= 1;
5151             //genSkipCond(&rFalseIfx,right,size,7);
5152             //rFalseIfx.condition ^= 1;
5153
5154             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5155             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5156
5157             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5158             if(rFalseIfx.condition)
5159               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5160             else
5161               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5162
5163           }
5164
5165
5166           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5167           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5168
5169           while(size--) {
5170
5171             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5172             emitSKPNZ;
5173             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5174           }
5175           rFalseIfx.condition ^= 1;
5176           //rFalseIfx.condition = 1;
5177           genSkipc(&rFalseIfx);
5178
5179           pic16_emitpLabel(truelbl->key);
5180
5181           if(ifx) ifx->generated = 1;
5182
5183
5184           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5185             goto check_carry;
5186
5187           return;
5188           // end of if (sign)
5189         } else {
5190
5191           /* compare word or long to an unsigned literal on the right.*/
5192
5193
5194           size--;
5195           if(lit < 0xff) {
5196             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5197             switch (lit) {
5198             case 0:
5199               break; /* handled above */
5200 /*
5201             case 0xff:
5202               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5203               while(size--)
5204                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5205               genSkipz2(&rFalseIfx,0);
5206               break;
5207 */
5208             default:
5209               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5210               while(--size)
5211                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5212
5213               emitSKPZ;
5214               if(rFalseIfx.condition)
5215                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5216               else
5217                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5218
5219
5220               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5221               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5222
5223               rFalseIfx.condition ^= 1;
5224               genSkipc(&rFalseIfx);
5225             }
5226
5227             pic16_emitpLabel(truelbl->key);
5228
5229             if(ifx) ifx->generated = 1;
5230
5231             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5232               goto check_carry;
5233
5234             return;
5235           }
5236
5237
5238           lit++;
5239           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5240           i = (lit >> (size*8)) & 0xff;
5241
5242           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5243           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5244
5245           while(size--) {
5246             i = (lit >> (size*8)) & 0xff;
5247
5248             if(i) {
5249               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5250               emitSKPNZ;
5251               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5252             } else {
5253               /* this byte of the lit is zero, 
5254                * if it's not the last then OR in the variable */
5255               if(size)
5256                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5257             }
5258           }
5259
5260
5261           pic16_emitpLabel(lbl->key);
5262
5263           rFalseIfx.condition ^= 1;
5264
5265           genSkipc(&rFalseIfx);
5266         }
5267
5268         if(sign)
5269           pic16_emitpLabel(truelbl->key);
5270         if(ifx) ifx->generated = 1;
5271
5272             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5273               goto check_carry;
5274
5275         return;
5276       }
5277     }
5278     /* Compare two variables */
5279
5280     DEBUGpic16_emitcode(";sign","%d",sign);
5281
5282     size--;
5283     if(sign) {
5284       /* Sigh. thus sucks... */
5285       if(size) {
5286         pCodeOp *pctemp;
5287         
5288         pctemp = pic16_popGetTempReg(1);
5289         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5291         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5292         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5293         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5294         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5295         pic16_popReleaseTempReg(pctemp, 1);
5296       } else {
5297         /* Signed char comparison */
5298         /* Special thanks to Nikolai Golovchenko for this snippet */
5299         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5300         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5301         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5302         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5303         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5304         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5305
5306         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5307         genSkipc(&rFalseIfx);
5308           
5309         if(ifx) ifx->generated = 1;
5310
5311             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5312               goto check_carry;
5313
5314         return;
5315       }
5316
5317     } else {
5318
5319       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5320       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5321     }
5322
5323
5324     /* The rest of the bytes of a multi-byte compare */
5325     while (size) {
5326
5327       emitSKPZ;
5328       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5329       size--;
5330
5331       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5332       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5333
5334
5335     }
5336
5337     pic16_emitpLabel(lbl->key);
5338
5339     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5340     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5341         (AOP_TYPE(result) == AOP_REG)) {
5342       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5343       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5344     } else {
5345       genSkipc(&rFalseIfx);
5346     }         
5347     //genSkipc(&rFalseIfx);
5348     if(ifx) ifx->generated = 1;
5349
5350
5351             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5352               goto check_carry;
5353
5354     return;
5355
5356   }
5357
5358 check_carry:
5359   if ((AOP_TYPE(result) != AOP_CRY) 
5360         && AOP_SIZE(result)) {
5361     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5362
5363     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5364
5365     pic16_outBitC(result);
5366   } else {
5367     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5368     /* if the result is used in the next
5369        ifx conditional branch then generate
5370        code a little differently */
5371     if (ifx )
5372       genIfxJump (ifx,"c");
5373     else
5374       pic16_outBitC(result);
5375     /* leave the result in acc */
5376   }
5377
5378 }
5379
5380 #else   /* old version of genCmp() */
5381
5382 /* new version of genCmp -- VR 20041012 */
5383 static void genCmp (operand *left,operand *right,
5384                     operand *result, iCode *ifx, int sign)
5385 {
5386   int size; //, offset = 0 ;
5387   unsigned long lit = 0L,i = 0;
5388   resolvedIfx rFalseIfx;
5389   int willCheckCarry=0;
5390   //  resolvedIfx rTrueIfx;
5391   symbol *truelbl;
5392   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5393
5394
5395   /* General concept:
5396    * subtract right from left if at the end the carry flag is set then we
5397    * know that left is greater than right */
5398             
5399   resolveIfx(&rFalseIfx,ifx);
5400   truelbl  = newiTempLabel(NULL);
5401   size = max(AOP_SIZE(left),AOP_SIZE(right));
5402
5403   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5404
5405   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5406    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5407   
5408
5409   /* if literal is on the right then swap with left */
5410   if ((AOP_TYPE(right) == AOP_LIT)) {
5411     operand *tmp = right ;
5412     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5413
5414       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5415
5416 //      lit = (lit - 1) & mask;
5417       right = left;
5418       left = tmp;
5419       rFalseIfx.condition ^= 1;
5420   } else
5421   if ((AOP_TYPE(left) == AOP_LIT)) {
5422     /* float compares are handled by support functions */
5423     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5424   }
5425
5426
5427   //if(IC_TRUE(ifx) == NULL)
5428   /* if left & right are bit variables */
5429   if (AOP_TYPE(left) == AOP_CRY &&
5430       AOP_TYPE(right) == AOP_CRY ) {
5431     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5432     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5433
5434   } else {
5435     symbol *lbl  = newiTempLabel(NULL);
5436
5437     if(AOP_TYPE(left) == AOP_LIT) {
5438       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5439
5440       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5441         willCheckCarry = 1;
5442       else willCheckCarry = 0;
5443
5444       /* Special cases */
5445       if((lit == 0) && (sign == 0)){
5446
5447         size--;
5448         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5449         while(size) 
5450           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5451
5452         genSkipz2(&rFalseIfx,0);
5453         if(ifx) ifx->generated = 1;
5454         return;
5455       }
5456
5457       if(size==1) {
5458         /* Special cases */
5459         lit &= 0xff;
5460         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5461           /* degenerate compare can never be true */
5462           if(rFalseIfx.condition == 0)
5463             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5464
5465           if(ifx) ifx->generated = 1;
5466           return;
5467         }
5468
5469         if(sign) {
5470           /* signed comparisons to a literal byte */
5471
5472           int lp1 = (lit+1) & 0xff;
5473
5474           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d",__LINE__,lit, rFalseIfx.condition);
5475           switch (lp1) {
5476           case 0:
5477             rFalseIfx.condition ^= 1;
5478             genSkipCond(&rFalseIfx,right,0,7);
5479             break;
5480           case 0x7f:
5481             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5482             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5483             genSkipz2(&rFalseIfx,1);
5484             break;
5485           default:
5486             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5487             
5488             if(rFalseIfx.condition)
5489               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5490             else
5491               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5492
5493             if(willCheckCarry) {
5494               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5495               else { emitSETC; emitCLRC; }
5496               
5497             } else {
5498               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5499             }              
5500                       
5501 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5502             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5503             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5504             rFalseIfx.condition ^= 1;
5505             genSkipc(&rFalseIfx);
5506 */
5507             break;
5508           }
5509         } else {
5510           /* unsigned comparisons to a literal byte */
5511
5512           switch(lit & 0xff ) {
5513           case 0:
5514             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5515             genSkipz2(&rFalseIfx,0);
5516             break;
5517           case 0x7f:
5518             rFalseIfx.condition ^= 1;
5519             genSkipCond(&rFalseIfx,right,0,7);
5520             break;
5521
5522           default:
5523             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5524             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5525             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5526             rFalseIfx.condition ^= 1;
5527             if (AOP_TYPE(result) == AOP_CRY)
5528               genSkipc(&rFalseIfx);
5529             else {
5530               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5531               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5532             }         
5533             break;
5534           }
5535         }
5536
5537         if(ifx) ifx->generated = 1;
5538         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5539                 goto check_carry;
5540         return;
5541
5542       } else {
5543
5544         /* Size is greater than 1 */
5545
5546         if(sign) {
5547           int lp1 = lit+1;
5548
5549           size--;
5550
5551           if(lp1 == 0) {
5552             /* this means lit = 0xffffffff, or -1 */
5553
5554
5555             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5556             rFalseIfx.condition ^= 1;
5557             genSkipCond(&rFalseIfx,right,size,7);
5558             if(ifx) ifx->generated = 1;
5559             return;
5560           }
5561
5562           if(lit == 0) {
5563             int s = size;
5564
5565             if(rFalseIfx.condition) {
5566               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5567               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5568             }
5569
5570             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5571             while(size--)
5572               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5573
5574
5575             emitSKPZ;
5576             if(rFalseIfx.condition) {
5577               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5578               pic16_emitpLabel(truelbl->key);
5579             }else {
5580               rFalseIfx.condition ^= 1;
5581               genSkipCond(&rFalseIfx,right,s,7);
5582             }
5583
5584             if(ifx) ifx->generated = 1;
5585             return;
5586           }
5587
5588           if((size == 1) &&  (0 == (lp1&0xff))) {
5589             /* lower byte of signed word is zero */
5590             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5591             i = ((lp1 >> 8) & 0xff) ^0x80;
5592             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5593             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5594             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5595             rFalseIfx.condition ^= 1;
5596             genSkipc(&rFalseIfx);
5597
5598
5599             if(ifx) ifx->generated = 1;
5600             return;
5601           }
5602
5603           if(lit & (0x80 << (size*8))) {
5604             /* Lit is less than zero */
5605             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5606             //rFalseIfx.condition ^= 1;
5607             //genSkipCond(&rFalseIfx,left,size,7);
5608             //rFalseIfx.condition ^= 1;
5609             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5610             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5611
5612             if(rFalseIfx.condition)
5613               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5614             else
5615               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5616
5617
5618           } else {
5619             /* Lit is greater than or equal to zero */
5620             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5621             //rFalseIfx.condition ^= 1;
5622             //genSkipCond(&rFalseIfx,right,size,7);
5623             //rFalseIfx.condition ^= 1;
5624
5625             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5626             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5627
5628             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5629             if(rFalseIfx.condition)
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5631             else
5632               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5633
5634           }
5635
5636
5637           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5638           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5639
5640           while(size--) {
5641
5642             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5643             emitSKPNZ;
5644             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5645           }
5646           rFalseIfx.condition ^= 1;
5647           //rFalseIfx.condition = 1;
5648           genSkipc(&rFalseIfx);
5649
5650           pic16_emitpLabel(truelbl->key);
5651
5652           if(ifx) ifx->generated = 1;
5653           return;
5654           // end of if (sign)
5655         } else {
5656
5657           /* compare word or long to an unsigned literal on the right.*/
5658
5659
5660           size--;
5661           if(lit < 0xff) {
5662             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5663             switch (lit) {
5664             case 0:
5665               break; /* handled above */
5666 /*
5667             case 0xff:
5668               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5669               while(size--)
5670                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5671               genSkipz2(&rFalseIfx,0);
5672               break;
5673 */
5674             default:
5675               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5676               while(--size)
5677                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5678
5679               emitSKPZ;
5680               if(rFalseIfx.condition)
5681                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5682               else
5683                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5684
5685
5686               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5687               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5688
5689               rFalseIfx.condition ^= 1;
5690               genSkipc(&rFalseIfx);
5691             }
5692
5693             pic16_emitpLabel(truelbl->key);
5694
5695             if(ifx) ifx->generated = 1;
5696             return;
5697           }
5698
5699
5700           lit++;
5701           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5702           i = (lit >> (size*8)) & 0xff;
5703
5704           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5705           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5706
5707           while(size--) {
5708             i = (lit >> (size*8)) & 0xff;
5709
5710             if(i) {
5711               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5712               emitSKPNZ;
5713               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5714             } else {
5715               /* this byte of the lit is zero, 
5716                * if it's not the last then OR in the variable */
5717               if(size)
5718                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5719             }
5720           }
5721
5722
5723           pic16_emitpLabel(lbl->key);
5724
5725           rFalseIfx.condition ^= 1;
5726
5727           genSkipc(&rFalseIfx);
5728         }
5729
5730         if(sign)
5731           pic16_emitpLabel(truelbl->key);
5732         if(ifx) ifx->generated = 1;
5733         return;
5734       }
5735     }
5736     /* Compare two variables */
5737
5738     DEBUGpic16_emitcode(";sign","%d",sign);
5739
5740     size--;
5741     if(sign) {
5742       /* Sigh. thus sucks... */
5743       if(size) {
5744         pCodeOp *pctemp;
5745         
5746         pctemp = pic16_popGetTempReg(1);
5747         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5748         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5749         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5750         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5751         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5752         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5753         pic16_popReleaseTempReg(pctemp, 1);
5754       } else {
5755         /* Signed char comparison */
5756         /* Special thanks to Nikolai Golovchenko for this snippet */
5757         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5758         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5759         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5760         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5761         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5762         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5763
5764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5765         genSkipc(&rFalseIfx);
5766           
5767         if(ifx) ifx->generated = 1;
5768         return;
5769       }
5770
5771     } else {
5772
5773       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5774       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5775     }
5776
5777
5778     /* The rest of the bytes of a multi-byte compare */
5779     while (size) {
5780
5781       emitSKPZ;
5782       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5783       size--;
5784
5785       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5786       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5787
5788
5789     }
5790
5791     pic16_emitpLabel(lbl->key);
5792
5793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5794     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5795         (AOP_TYPE(result) == AOP_REG)) {
5796       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5797       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5798     } else {
5799       genSkipc(&rFalseIfx);
5800     }         
5801     //genSkipc(&rFalseIfx);
5802     if(ifx) ifx->generated = 1;
5803
5804     return;
5805
5806   }
5807
5808 check_carry:
5809   if ((AOP_TYPE(result) != AOP_CRY) 
5810         && AOP_SIZE(result)) {
5811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5812
5813     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5814
5815     pic16_outBitC(result);
5816   } else {
5817     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5818     /* if the result is used in the next
5819        ifx conditional branch then generate
5820        code a little differently */
5821     if (ifx )
5822       genIfxJump (ifx,"c");
5823     else
5824       pic16_outBitC(result);
5825     /* leave the result in acc */
5826   }
5827
5828 }
5829 #endif
5830
5831
5832
5833 /*-----------------------------------------------------------------*/
5834 /* genCmpGt :- greater than comparison                             */
5835 /*-----------------------------------------------------------------*/
5836 static void genCmpGt (iCode *ic, iCode *ifx)
5837 {
5838     operand *left, *right, *result;
5839     sym_link *letype , *retype;
5840     int sign ;
5841
5842     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5843     left = IC_LEFT(ic);
5844     right= IC_RIGHT(ic);
5845     result = IC_RESULT(ic);
5846
5847     letype = getSpec(operandType(left));
5848     retype =getSpec(operandType(right));
5849     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5850     /* assign the amsops */
5851     pic16_aopOp (left,ic,FALSE);
5852     pic16_aopOp (right,ic,FALSE);
5853     pic16_aopOp (result,ic,TRUE);
5854
5855     genCmp(right, left, result, ifx, sign);
5856
5857     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5858     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5859     pic16_freeAsmop(result,NULL,ic,TRUE); 
5860 }
5861
5862 /*-----------------------------------------------------------------*/
5863 /* genCmpLt - less than comparisons                                */
5864 /*-----------------------------------------------------------------*/
5865 static void genCmpLt (iCode *ic, iCode *ifx)
5866 {
5867     operand *left, *right, *result;
5868     sym_link *letype , *retype;
5869     int sign ;
5870
5871     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5872     left = IC_LEFT(ic);
5873     right= IC_RIGHT(ic);
5874     result = IC_RESULT(ic);
5875
5876     letype = getSpec(operandType(left));
5877     retype =getSpec(operandType(right));
5878     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5879
5880     /* assign the amsops */
5881     pic16_aopOp (left,ic,FALSE);
5882     pic16_aopOp (right,ic,FALSE);
5883     pic16_aopOp (result,ic,TRUE);
5884
5885     genCmp(left, right, result, ifx, sign);
5886
5887     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5888     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5889     pic16_freeAsmop(result,NULL,ic,TRUE); 
5890 }
5891
5892 #if 0
5893 // not needed ATM
5894 // FIXME reenable literal optimisation when the pic16 port is stable
5895
5896 /*-----------------------------------------------------------------*/
5897 /* genc16bit2lit - compare a 16 bit value to a literal             */
5898 /*-----------------------------------------------------------------*/
5899 static void genc16bit2lit(operand *op, int lit, int offset)
5900 {
5901   int i;
5902
5903   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5904   if( (lit&0xff) == 0) 
5905     i=1;
5906   else
5907     i=0;
5908
5909   switch( BYTEofLONG(lit,i)) { 
5910   case 0:
5911     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5912     break;
5913   case 1:
5914     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5915     break;
5916   case 0xff:
5917     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5918     break;
5919   default:
5920     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5921     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5922   }
5923
5924   i ^= 1;
5925
5926   switch( BYTEofLONG(lit,i)) { 
5927   case 0:
5928     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5929     break;
5930   case 1:
5931     emitSKPNZ;
5932     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5933     break;
5934   case 0xff:
5935     emitSKPNZ;
5936     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5937     break;
5938   default:
5939     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5940     emitSKPNZ;
5941     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5942
5943   }
5944
5945 }
5946 #endif
5947
5948 #if 0
5949 // not needed ATM
5950 /*-----------------------------------------------------------------*/
5951 /* gencjneshort - compare and jump if not equal                    */
5952 /*-----------------------------------------------------------------*/
5953 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5954 {
5955   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5956   int offset = 0;
5957   int res_offset = 0;  /* the result may be a different size then left or right */
5958   int res_size = AOP_SIZE(result);
5959   resolvedIfx rIfx;
5960   symbol *lbl, *lbl_done;
5961
5962   unsigned long lit = 0L;
5963   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5964
5965   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5966   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5967   if(result)
5968     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5969   resolveIfx(&rIfx,ifx);
5970   lbl =  newiTempLabel(NULL);
5971   lbl_done =  newiTempLabel(NULL);
5972
5973
5974   /* if the left side is a literal or 
5975      if the right is in a pointer register and left 
5976      is not */
5977   if ((AOP_TYPE(left) == AOP_LIT) || 
5978       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5979     operand *t = right;
5980     right = left;
5981     left = t;
5982   }
5983   if(AOP_TYPE(right) == AOP_LIT)
5984     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5985
5986   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5987     preserve_result = 1;
5988
5989   if(result && !preserve_result)
5990     {
5991       int i;
5992       for(i = 0; i < AOP_SIZE(result); i++)
5993         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5994     }
5995
5996
5997   /* if the right side is a literal then anything goes */
5998   if (AOP_TYPE(right) == AOP_LIT &&
5999       AOP_TYPE(left) != AOP_DIR ) {
6000     switch(size) {
6001     case 2:
6002       genc16bit2lit(left, lit, 0);
6003       emitSKPZ;
6004       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6005       break;
6006     default:
6007       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6008       while (size--) {
6009         if(lit & 0xff) {
6010           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6011           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6012         } else {
6013           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6014         }
6015
6016         emitSKPZ;
6017         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6018         offset++;
6019         if(res_offset < res_size-1)
6020           res_offset++;
6021         lit >>= 8;
6022       }
6023       break;
6024     }
6025   }
6026
6027   /* if the right side is in a register or in direct space or
6028      if the left is a pointer register & right is not */    
6029   else if (AOP_TYPE(right) == AOP_REG ||
6030            AOP_TYPE(right) == AOP_DIR || 
6031            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6032            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6033     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6034     int lbl_key = lbl->key;
6035
6036     if(result) {
6037       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6038       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6039     }else {
6040       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6041       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6042               __FUNCTION__,__LINE__);
6043       return;
6044     }
6045    
6046 /*     switch(size) { */
6047 /*     case 2: */
6048 /*       genc16bit2lit(left, lit, 0); */
6049 /*       emitSKPNZ; */
6050 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6051 /*       break; */
6052 /*     default: */
6053     while (size--) {
6054       int emit_skip=1;
6055       if((AOP_TYPE(left) == AOP_DIR) && 
6056          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6057
6058         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6059         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6060
6061       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6062             
6063         switch (lit & 0xff) {
6064         case 0:
6065           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6066           break;
6067         case 1:
6068           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6069           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6070           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6071           emit_skip=0;
6072           break;
6073         case 0xff:
6074           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6075           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6076           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6077           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6078           emit_skip=0;
6079           break;
6080         default:
6081           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6082           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6083         }
6084         lit >>= 8;
6085
6086       } else {
6087         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6088       }
6089       if(emit_skip) {
6090         if(AOP_TYPE(result) == AOP_CRY) {
6091           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6092           if(rIfx.condition)
6093             emitSKPNZ;
6094           else
6095             emitSKPZ;
6096           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6097         } else {
6098           /* fix me. probably need to check result size too */
6099           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6100           if(rIfx.condition)
6101             emitSKPZ;
6102           else
6103             emitSKPNZ;
6104           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6105           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6106         }
6107         if(ifx)
6108           ifx->generated=1;
6109       }
6110       emit_skip++;
6111       offset++;
6112       if(res_offset < res_size-1)
6113         res_offset++;
6114     }
6115 /*       break; */
6116 /*     } */
6117   } else if(AOP_TYPE(right) == AOP_REG &&
6118             AOP_TYPE(left) != AOP_DIR){
6119
6120     while(size--) {
6121       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6122       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6123       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6124       if(rIfx.condition)
6125         emitSKPNZ;
6126       else
6127         emitSKPZ;
6128       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6129       offset++;
6130       if(res_offset < res_size-1)
6131         res_offset++;
6132     }
6133       
6134   }else{
6135     /* right is a pointer reg need both a & b */
6136     while(size--) {
6137       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6138       if(strcmp(l,"b"))
6139         pic16_emitcode("mov","b,%s",l);
6140       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6141       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6142       offset++;
6143     }
6144   }
6145
6146   if(result && preserve_result)
6147     {
6148       int i;
6149       for(i = 0; i < AOP_SIZE(result); i++)
6150         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6151     }
6152
6153   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6154
6155   if(result && preserve_result)
6156     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6157
6158   if(!rIfx.condition)
6159     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6160
6161   pic16_emitpLabel(lbl->key);
6162
6163   if(result && preserve_result)
6164     {
6165       int i;
6166       for(i = 0; i < AOP_SIZE(result); i++)
6167         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6168
6169       pic16_emitpLabel(lbl_done->key);
6170    }
6171
6172   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6173
6174   if(ifx)
6175     ifx->generated = 1;
6176 }
6177 #endif
6178
6179 #if 0
6180 /*-----------------------------------------------------------------*/
6181 /* gencjne - compare and jump if not equal                         */
6182 /*-----------------------------------------------------------------*/
6183 static void gencjne(operand *left, operand *right, iCode *ifx)
6184 {
6185     symbol *tlbl  = newiTempLabel(NULL);
6186
6187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6188     gencjneshort(left, right, lbl);
6189
6190     pic16_emitcode("mov","a,%s",one);
6191     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6192     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6193     pic16_emitcode("clr","a");
6194     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6195
6196     pic16_emitpLabel(lbl->key);
6197     pic16_emitpLabel(tlbl->key);
6198
6199 }
6200 #endif
6201
6202
6203 /*-----------------------------------------------------------------*/
6204 /* is_LitOp - check if operand has to be treated as literal        */
6205 /*-----------------------------------------------------------------*/
6206 static bool is_LitOp(operand *op)
6207 {
6208   return (AOP_TYPE(op) == AOP_LIT)
6209       || ( (AOP_TYPE(op) == AOP_PCODE)
6210           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6211               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
6212 }
6213
6214 /*-----------------------------------------------------------------*/
6215 /* is_LitAOp - check if operand has to be treated as literal        */
6216 /*-----------------------------------------------------------------*/
6217 static bool is_LitAOp(asmop *aop)
6218 {
6219   return (aop->type == AOP_LIT)
6220       || ( (aop->type == AOP_PCODE)
6221           && ( (aop->aopu.pcop->type == PO_LITERAL)
6222               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
6223 }
6224
6225
6226
6227 /*-----------------------------------------------------------------*/
6228 /* genCmpEq - generates code for equal to                          */
6229 /*-----------------------------------------------------------------*/
6230 static void genCmpEq (iCode *ic, iCode *ifx)
6231 {
6232   operand *left, *right, *result;
6233   symbol *falselbl = newiTempLabel(NULL);
6234   symbol *donelbl = newiTempLabel(NULL);
6235
6236   int preserve_result = 0;
6237   int generate_result = 0;
6238   int i=0;
6239
6240   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6241   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6242   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6243  
6244   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6246
6247   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6248     {
6249       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6250       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6251       goto release;
6252     }
6253
6254   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6255     {
6256       operand *tmp = right ;
6257       right = left;
6258       left = tmp;
6259     }
6260
6261   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6262     preserve_result = 1;
6263
6264   if(result && AOP_SIZE(result))
6265     generate_result = 1;
6266
6267   if(generate_result && !preserve_result)
6268     {
6269       for(i = 0; i < AOP_SIZE(result); i++)
6270         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6271     }
6272
6273   for(i=0; i < AOP_SIZE(left); i++)
6274     {
6275       if(AOP_TYPE(left) != AOP_ACC)
6276         {
6277           if(is_LitOp(left))
6278             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6279           else
6280             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6281         }
6282       if(is_LitOp(right))
6283         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6284       else
6285         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6286
6287       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6288     }
6289
6290   // result == true
6291
6292   if(generate_result && preserve_result)
6293     {
6294       for(i = 0; i < AOP_SIZE(result); i++)
6295         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6296     }
6297
6298   if(generate_result)
6299     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6300
6301   if(generate_result && preserve_result)
6302     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6303
6304   if(ifx && IC_TRUE(ifx))
6305     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6306
6307   if(ifx && IC_FALSE(ifx))
6308     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6309
6310   pic16_emitpLabel(falselbl->key);
6311
6312   // result == false
6313
6314   if(ifx && IC_FALSE(ifx))
6315     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6316
6317   if(generate_result && preserve_result)
6318     {
6319       for(i = 0; i < AOP_SIZE(result); i++)
6320         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6321     }
6322
6323   pic16_emitpLabel(donelbl->key);
6324
6325   if(ifx)
6326     ifx->generated = 1;
6327
6328 release:
6329   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331   pic16_freeAsmop(result,NULL,ic,TRUE);
6332
6333 }
6334
6335
6336 #if 0
6337 // old version kept for reference
6338
6339 /*-----------------------------------------------------------------*/
6340 /* genCmpEq - generates code for equal to                          */
6341 /*-----------------------------------------------------------------*/
6342 static void genCmpEq (iCode *ic, iCode *ifx)
6343 {
6344     operand *left, *right, *result;
6345     unsigned long lit = 0L;
6346     int size,offset=0;
6347     symbol *falselbl  = newiTempLabel(NULL);
6348
6349
6350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6351
6352     if(ifx)
6353       DEBUGpic16_emitcode ("; ifx is non-null","");
6354     else
6355       DEBUGpic16_emitcode ("; ifx is null","");
6356
6357     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6358     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6359     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6360
6361     size = max(AOP_SIZE(left),AOP_SIZE(right));
6362
6363     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6364
6365     /* if literal, literal on the right or 
6366     if the right is in a pointer register and left 
6367     is not */
6368     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6369         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6370       operand *tmp = right ;
6371       right = left;
6372       left = tmp;
6373     }
6374
6375
6376     if(ifx && !AOP_SIZE(result)){
6377         symbol *tlbl;
6378         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6379         /* if they are both bit variables */
6380         if (AOP_TYPE(left) == AOP_CRY &&
6381             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6382                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6383             if(AOP_TYPE(right) == AOP_LIT){
6384                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6385                 if(lit == 0L){
6386                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6387                     pic16_emitcode("cpl","c");
6388                 } else if(lit == 1L) {
6389                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6390                 } else {
6391                     pic16_emitcode("clr","c");
6392                 }
6393                 /* AOP_TYPE(right) == AOP_CRY */
6394             } else {
6395                 symbol *lbl = newiTempLabel(NULL);
6396                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6397                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6398                 pic16_emitcode("cpl","c");
6399                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6400             }
6401             /* if true label then we jump if condition
6402             supplied is true */
6403             tlbl = newiTempLabel(NULL);
6404             if ( IC_TRUE(ifx) ) {
6405                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6406                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6407             } else {
6408                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6409                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6410             }
6411             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6412
6413                 {
6414                 /* left and right are both bit variables, result is carry */
6415                         resolvedIfx rIfx;
6416               
6417                         resolveIfx(&rIfx,ifx);
6418
6419                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6420                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6421                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6422                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6423                         genSkipz2(&rIfx,0);
6424                 }
6425         } else {
6426
6427                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6428
6429                         /* They're not both bit variables. Is the right a literal? */
6430                         if(AOP_TYPE(right) == AOP_LIT) {
6431                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6432             
6433                         switch(size) {
6434
6435                                 case 1:
6436                                         switch(lit & 0xff) {
6437                                                 case 1:
6438                                                                 if ( IC_TRUE(ifx) ) {
6439                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6440                                                                         emitSKPNZ;
6441                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6442                                                                 } else {
6443                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6444                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6445                                                                 }
6446                                                                 break;
6447                                                 case 0xff:
6448                                                                 if ( IC_TRUE(ifx) ) {
6449                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6450                                                                         emitSKPNZ;
6451                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6452                                                                 } else {
6453                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6454                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6455                                                                 }
6456                                                                 break;
6457                                                 default:
6458                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6459                                                                 if(lit)
6460                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6461                                                                 genSkip(ifx,'z');
6462                                         } // switch lit
6463
6464
6465                                         /* end of size == 1 */
6466                                         break;
6467               
6468                                 case 2:
6469                                         genc16bit2lit(left,lit,offset);
6470                                         genSkip(ifx,'z');
6471                                         break;
6472                                         /* end of size == 2 */
6473
6474                                 default:
6475                                         /* size is 4 */
6476                                         if(lit==0) {
6477                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6478                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6479                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6480                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6481                                                 genSkip(ifx,'z');
6482                                         } else {
6483                                                 /* search for patterns that can be optimized */
6484
6485                                                 genc16bit2lit(left,lit,0);
6486                                                 lit >>= 16;
6487                                                 if(lit) {
6488                                                                 if(IC_TRUE(ifx))
6489                                                                 emitSKPZ; // if hi word unequal
6490                                                                 else
6491                                                                 emitSKPNZ; // if hi word equal
6492                                                                 // fail early
6493                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6494                                                         genc16bit2lit(left,lit,2);
6495                                                         genSkip(ifx,'z');
6496                                                 } else {
6497                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6498                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6499                                                         genSkip(ifx,'z');
6500                                                 }
6501                                         }
6502                                                 pic16_emitpLabel(falselbl->key);
6503                                                 break;
6504
6505                         } // switch size
6506           
6507                         ifx->generated = 1;
6508                         goto release ;
6509             
6510
6511           } else if(AOP_TYPE(right) == AOP_CRY ) {
6512             /* we know the left is not a bit, but that the right is */
6513             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6514             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6515                       pic16_popGet(AOP(right),offset));
6516             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6517
6518             /* if the two are equal, then W will be 0 and the Z bit is set
6519              * we could test Z now, or go ahead and check the high order bytes if
6520              * the variable we're comparing is larger than a byte. */
6521
6522             while(--size)
6523               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6524
6525             if ( IC_TRUE(ifx) ) {
6526               emitSKPNZ;
6527               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6528               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6529             } else {
6530               emitSKPZ;
6531               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6532               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6533             }
6534
6535           } else {
6536             /* They're both variables that are larger than bits */
6537             int s = size;
6538
6539             tlbl = newiTempLabel(NULL);
6540
6541             while(size--) {
6542               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6543               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6544
6545               if ( IC_TRUE(ifx) ) {
6546                 if(size) {
6547                   emitSKPZ;
6548                 
6549                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6550
6551                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6552                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6553                 } else {
6554                   emitSKPNZ;
6555
6556                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6557
6558
6559                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6560                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6561                 }
6562               } else {
6563                 emitSKPZ;
6564
6565                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6566
6567                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6568                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6569               }
6570               offset++;
6571             }
6572             if(s>1 && IC_TRUE(ifx)) {
6573               pic16_emitpLabel(tlbl->key);
6574               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6575             }
6576           }
6577         }
6578         /* mark the icode as generated */
6579         ifx->generated = 1;
6580         goto release ;
6581     }
6582
6583     /* if they are both bit variables */
6584     if (AOP_TYPE(left) == AOP_CRY &&
6585         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6586         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6587         if(AOP_TYPE(right) == AOP_LIT){
6588             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6589             if(lit == 0L){
6590                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6591                 pic16_emitcode("cpl","c");
6592             } else if(lit == 1L) {
6593                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6594             } else {
6595                 pic16_emitcode("clr","c");
6596             }
6597             /* AOP_TYPE(right) == AOP_CRY */
6598         } else {
6599             symbol *lbl = newiTempLabel(NULL);
6600             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6601             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6602             pic16_emitcode("cpl","c");
6603             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6604         }
6605         /* c = 1 if egal */
6606         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6607             pic16_outBitC(result);
6608             goto release ;
6609         }
6610         if (ifx) {
6611             genIfxJump (ifx,"c");
6612             goto release ;
6613         }
6614         /* if the result is used in an arithmetic operation
6615         then put the result in place */
6616         pic16_outBitC(result);
6617     } else {
6618       
6619       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6620       gencjne(left,right,result,ifx);
6621 /*
6622       if(ifx) 
6623         gencjne(left,right,newiTempLabel(NULL));
6624       else {
6625         if(IC_TRUE(ifx)->key)
6626           gencjne(left,right,IC_TRUE(ifx)->key);
6627         else
6628           gencjne(left,right,IC_FALSE(ifx)->key);
6629         ifx->generated = 1;
6630         goto release ;
6631       }
6632       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6633         pic16_aopPut(AOP(result),"a",0);
6634         goto release ;
6635       }
6636
6637       if (ifx) {
6638         genIfxJump (ifx,"a");
6639         goto release ;
6640       }
6641 */
6642       /* if the result is used in an arithmetic operation
6643          then put the result in place */
6644 /*
6645       if (AOP_TYPE(result) != AOP_CRY) 
6646         pic16_outAcc(result);
6647 */
6648       /* leave the result in acc */
6649     }
6650
6651 release:
6652     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6653     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6654     pic16_freeAsmop(result,NULL,ic,TRUE);
6655 }
6656 #endif
6657
6658 /*-----------------------------------------------------------------*/
6659 /* ifxForOp - returns the icode containing the ifx for operand     */
6660 /*-----------------------------------------------------------------*/
6661 static iCode *ifxForOp ( operand *op, iCode *ic )
6662 {
6663     /* if true symbol then needs to be assigned */
6664     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6665     if (IS_TRUE_SYMOP(op))
6666         return NULL ;
6667
6668     /* if this has register type condition and
6669     the next instruction is ifx with the same operand
6670     and live to of the operand is upto the ifx only then */
6671     if (ic->next
6672         && ic->next->op == IFX
6673         && IC_COND(ic->next)->key == op->key
6674         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6675         ) {
6676                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6677           return ic->next;
6678     }
6679
6680     if (ic->next &&
6681         ic->next->op == IFX &&
6682         IC_COND(ic->next)->key == op->key) {
6683       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6684       return ic->next;
6685     }
6686
6687     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6688     if (ic->next &&
6689         ic->next->op == IFX)
6690       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6691
6692     if (ic->next &&
6693         ic->next->op == IFX &&
6694         IC_COND(ic->next)->key == op->key) {
6695       DEBUGpic16_emitcode ("; "," key is okay");
6696       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6697                            OP_SYMBOL(op)->liveTo,
6698                            ic->next->seq);
6699     }
6700
6701 #if 0
6702     /* the code below is completely untested
6703      * it just allows ulong2fs.c compile -- VR */
6704          
6705     ic = ic->next;
6706     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6707                                         __FILE__, __FUNCTION__, __LINE__);
6708         
6709     /* if this has register type condition and
6710     the next instruction is ifx with the same operand
6711     and live to of the operand is upto the ifx only then */
6712     if (ic->next &&
6713         ic->next->op == IFX &&
6714         IC_COND(ic->next)->key == op->key &&
6715         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6716         return ic->next;
6717
6718     if (ic->next &&
6719         ic->next->op == IFX &&
6720         IC_COND(ic->next)->key == op->key) {
6721       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6722       return ic->next;
6723     }
6724
6725     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6726                                         __FILE__, __FUNCTION__, __LINE__);
6727
6728 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6729 #endif
6730
6731     return NULL;
6732 }
6733 /*-----------------------------------------------------------------*/
6734 /* genAndOp - for && operation                                     */
6735 /*-----------------------------------------------------------------*/
6736 static void genAndOp (iCode *ic)
6737 {
6738     operand *left,*right, *result;
6739 /*     symbol *tlbl; */
6740
6741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6742     /* note here that && operations that are in an
6743     if statement are taken away by backPatchLabels
6744     only those used in arthmetic operations remain */
6745     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6746     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6747     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6748
6749     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6750
6751     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6752     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6753     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6754
6755     /* if both are bit variables */
6756 /*     if (AOP_TYPE(left) == AOP_CRY && */
6757 /*         AOP_TYPE(right) == AOP_CRY ) { */
6758 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6759 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6760 /*         pic16_outBitC(result); */
6761 /*     } else { */
6762 /*         tlbl = newiTempLabel(NULL); */
6763 /*         pic16_toBoolean(left);     */
6764 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6765 /*         pic16_toBoolean(right); */
6766 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6767 /*         pic16_outBitAcc(result); */
6768 /*     } */
6769
6770     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6772     pic16_freeAsmop(result,NULL,ic,TRUE);
6773 }
6774
6775
6776 /*-----------------------------------------------------------------*/
6777 /* genOrOp - for || operation                                      */
6778 /*-----------------------------------------------------------------*/
6779 /*
6780   tsd pic port -
6781   modified this code, but it doesn't appear to ever get called
6782 */
6783
6784 static void genOrOp (iCode *ic)
6785 {
6786     operand *left,*right, *result;
6787     symbol *tlbl;
6788
6789     /* note here that || operations that are in an
6790     if statement are taken away by backPatchLabels
6791     only those used in arthmetic operations remain */
6792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6793     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6794     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6795     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6796
6797     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6798
6799     /* if both are bit variables */
6800     if (AOP_TYPE(left) == AOP_CRY &&
6801         AOP_TYPE(right) == AOP_CRY ) {
6802       pic16_emitcode("clrc","");
6803       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6804                AOP(left)->aopu.aop_dir,
6805                AOP(left)->aopu.aop_dir);
6806       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6807                AOP(right)->aopu.aop_dir,
6808                AOP(right)->aopu.aop_dir);
6809       pic16_emitcode("setc","");
6810
6811     } else {
6812         tlbl = newiTempLabel(NULL);
6813         pic16_toBoolean(left);
6814         emitSKPZ;
6815         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6816         pic16_toBoolean(right);
6817         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6818
6819         pic16_outBitAcc(result);
6820     }
6821
6822     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6823     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6824     pic16_freeAsmop(result,NULL,ic,TRUE);            
6825 }
6826
6827 /*-----------------------------------------------------------------*/
6828 /* isLiteralBit - test if lit == 2^n                               */
6829 /*-----------------------------------------------------------------*/
6830 static int isLiteralBit(unsigned long lit)
6831 {
6832     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6833     0x100L,0x200L,0x400L,0x800L,
6834     0x1000L,0x2000L,0x4000L,0x8000L,
6835     0x10000L,0x20000L,0x40000L,0x80000L,
6836     0x100000L,0x200000L,0x400000L,0x800000L,
6837     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6838     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6839     int idx;
6840     
6841     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6842     for(idx = 0; idx < 32; idx++)
6843         if(lit == pw[idx])
6844             return idx+1;
6845     return 0;
6846 }
6847
6848 /*-----------------------------------------------------------------*/
6849 /* continueIfTrue -                                                */
6850 /*-----------------------------------------------------------------*/
6851 static void continueIfTrue (iCode *ic)
6852 {
6853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6854     if(IC_TRUE(ic))
6855         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6856     ic->generated = 1;
6857 }
6858
6859 /*-----------------------------------------------------------------*/
6860 /* jmpIfTrue -                                                     */
6861 /*-----------------------------------------------------------------*/
6862 static void jumpIfTrue (iCode *ic)
6863 {
6864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6865     if(!IC_TRUE(ic))
6866         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6867     ic->generated = 1;
6868 }
6869
6870 /*-----------------------------------------------------------------*/
6871 /* jmpTrueOrFalse -                                                */
6872 /*-----------------------------------------------------------------*/
6873 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6874 {
6875     // ugly but optimized by peephole
6876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6877     if(IC_TRUE(ic)){
6878         symbol *nlbl = newiTempLabel(NULL);
6879         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6880         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6881         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6882         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6883     }
6884     else{
6885         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6886         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6887     }
6888     ic->generated = 1;
6889 }
6890
6891 /*-----------------------------------------------------------------*/
6892 /* genAnd  - code for and                                          */
6893 /*-----------------------------------------------------------------*/
6894 static void genAnd (iCode *ic, iCode *ifx)
6895 {
6896   operand *left, *right, *result;
6897   int size, offset=0;  
6898   unsigned long lit = 0L;
6899   int bytelit = 0;
6900   resolvedIfx rIfx;
6901
6902
6903   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6904   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6905   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6906   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6907
6908   resolveIfx(&rIfx,ifx);
6909
6910   /* if left is a literal & right is not then exchange them */
6911   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6912       AOP_NEEDSACC(left)) {
6913     operand *tmp = right ;
6914     right = left;
6915     left = tmp;
6916   }
6917
6918   /* if result = right then exchange them */
6919   if(pic16_sameRegs(AOP(result),AOP(right))){
6920     operand *tmp = right ;
6921     right = left;
6922     left = tmp;
6923   }
6924
6925   /* if right is bit then exchange them */
6926   if (AOP_TYPE(right) == AOP_CRY &&
6927       AOP_TYPE(left) != AOP_CRY){
6928     operand *tmp = right ;
6929     right = left;
6930     left = tmp;
6931   }
6932   if(AOP_TYPE(right) == AOP_LIT)
6933     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6934
6935   size = AOP_SIZE(result);
6936
6937   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6938
6939   // if(bit & yy)
6940   // result = bit & yy;
6941   if (AOP_TYPE(left) == AOP_CRY){
6942     // c = bit & literal;
6943     if(AOP_TYPE(right) == AOP_LIT){
6944       if(lit & 1) {
6945         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6946           // no change
6947           goto release;
6948         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6949       } else {
6950         // bit(result) = 0;
6951         if(size && (AOP_TYPE(result) == AOP_CRY)){
6952           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6953           goto release;
6954         }
6955         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6956           jumpIfTrue(ifx);
6957           goto release;
6958         }
6959         pic16_emitcode("clr","c");
6960       }
6961     } else {
6962       if (AOP_TYPE(right) == AOP_CRY){
6963         // c = bit & bit;
6964         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6965         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6966       } else {
6967         // c = bit & val;
6968         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6969         // c = lsb
6970         pic16_emitcode("rrc","a");
6971         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6972       }
6973     }
6974     // bit = c
6975     // val = c
6976     if(size)
6977       pic16_outBitC(result);
6978     // if(bit & ...)
6979     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6980       genIfxJump(ifx, "c");           
6981     goto release ;
6982   }
6983
6984   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6985   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6986   if((AOP_TYPE(right) == AOP_LIT) &&
6987      (AOP_TYPE(result) == AOP_CRY) &&
6988      (AOP_TYPE(left) != AOP_CRY)){
6989     int posbit = isLiteralBit(lit);
6990     /* left &  2^n */
6991     if(posbit){
6992       posbit--;
6993       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6994       // bit = left & 2^n
6995       if(size)
6996         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6997       // if(left &  2^n)
6998       else{
6999         if(ifx){
7000 /*
7001           if(IC_TRUE(ifx)) {
7002             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7003             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7004           } else {
7005             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7006             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7007           }
7008 */
7009         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7010         size = AOP_SIZE(left);
7011
7012         {
7013           int bp = posbit, ofs=0;
7014           
7015             while(bp > 7) {
7016               bp -= 8;
7017               ofs++;
7018             }
7019         
7020           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7021                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7022
7023         }
7024 /*
7025           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7026                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7027 */
7028           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7029           
7030           ifx->generated = 1;
7031         }
7032         goto release;
7033       }
7034     } else {
7035       symbol *tlbl = newiTempLabel(NULL);
7036       int sizel = AOP_SIZE(left);
7037
7038       if(size)
7039         emitSETC;
7040
7041       while(sizel--) {
7042         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7043
7044           /* patch provided by Aaron Colwell */
7045           if((posbit = isLiteralBit(bytelit)) != 0) {
7046               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7047                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7048                                                 (posbit-1),0, PO_GPR_REGISTER));
7049
7050               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7051 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7052           } else {
7053               if (bytelit == 0xff) {
7054                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7055                    * a peephole could optimize it out -- VR */
7056                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7057               } else {
7058                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7059                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7060               }
7061
7062               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7063                             pic16_popGetLabel(tlbl->key));
7064           }
7065         
7066 #if 0
7067           /* old code, left here for reference -- VR 09/2004 */
7068           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7069           // byte ==  2^n ?
7070           if((posbit = isLiteralBit(bytelit)) != 0)
7071             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7072           else{
7073             if(bytelit != 0x0FFL)
7074               pic16_emitcode("anl","a,%s",
7075                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7076             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7077           }
7078 #endif
7079         }
7080         offset++;
7081       }
7082       // bit = left & literal
7083       if(size) {
7084         emitCLRC;
7085         pic16_emitpLabel(tlbl->key);
7086       }
7087       // if(left & literal)
7088       else {
7089         if(ifx) {
7090           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7091           pic16_emitpLabel(tlbl->key);
7092           ifx->generated = 1;
7093         }
7094         goto release;
7095       }
7096     }
7097
7098     pic16_outBitC(result);
7099     goto release ;
7100   }
7101
7102   /* if left is same as result */
7103   if(pic16_sameRegs(AOP(result),AOP(left))){
7104     int know_W = -1;
7105     for(;size--; offset++,lit>>=8) {
7106       if(AOP_TYPE(right) == AOP_LIT){
7107         switch(lit & 0xff) {
7108         case 0x00:
7109           /*  and'ing with 0 has clears the result */
7110 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7111           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7112           break;
7113         case 0xff:
7114           /* and'ing with 0xff is a nop when the result and left are the same */
7115           break;
7116
7117         default:
7118           {
7119             int p = my_powof2( (~lit) & 0xff );
7120             if(p>=0) {
7121               /* only one bit is set in the literal, so use a bcf instruction */
7122 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7123               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7124
7125             } else {
7126               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7127               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7128               if(know_W != (lit&0xff))
7129                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7130               know_W = lit &0xff;
7131               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7132             }
7133           }    
7134         }
7135       } else {
7136         if (AOP_TYPE(left) == AOP_ACC) {
7137           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7138         } else {                    
7139           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7140           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7141
7142         }
7143       }
7144     }
7145
7146   } else {
7147     // left & result in different registers
7148     if(AOP_TYPE(result) == AOP_CRY){
7149       // result = bit
7150       // if(size), result in bit
7151       // if(!size && ifx), conditional oper: if(left & right)
7152       symbol *tlbl = newiTempLabel(NULL);
7153       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7154       if(size)
7155         pic16_emitcode("setb","c");
7156       while(sizer--){
7157         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7158         pic16_emitcode("anl","a,%s",
7159                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7160         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7161         offset++;
7162       }
7163       if(size){
7164         CLRC;
7165         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7166         pic16_outBitC(result);
7167       } else if(ifx)
7168         jmpTrueOrFalse(ifx, tlbl);
7169     } else {
7170       for(;(size--);offset++) {
7171         // normal case
7172         // result = left & right
7173         if(AOP_TYPE(right) == AOP_LIT){
7174           int t = (lit >> (offset*8)) & 0x0FFL;
7175           switch(t) { 
7176           case 0x00:
7177             pic16_emitcode("clrf","%s",
7178                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7179             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7180             break;
7181           case 0xff:
7182             pic16_emitcode("movf","%s,w",
7183                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7184             pic16_emitcode("movwf","%s",
7185                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7186             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7187             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7188             break;
7189           default:
7190             pic16_emitcode("movlw","0x%x",t);
7191             pic16_emitcode("andwf","%s,w",
7192                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7193             pic16_emitcode("movwf","%s",
7194                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7195               
7196             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7197             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7198             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7199           }
7200           continue;
7201         }
7202
7203         if (AOP_TYPE(left) == AOP_ACC) {
7204           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7205           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7206         } else {
7207           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7208           pic16_emitcode("andwf","%s,w",
7209                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7210           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7211           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7212         }
7213         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7214         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7215       }
7216     }
7217   }
7218
7219   release :
7220     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7222   pic16_freeAsmop(result,NULL,ic,TRUE);     
7223 }
7224
7225 /*-----------------------------------------------------------------*/
7226 /* genOr  - code for or                                            */
7227 /*-----------------------------------------------------------------*/
7228 static void genOr (iCode *ic, iCode *ifx)
7229 {
7230     operand *left, *right, *result;
7231     int size, offset=0;
7232     unsigned long lit = 0L;
7233
7234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7235
7236     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7237     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7238     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7239
7240     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7241
7242     /* if left is a literal & right is not then exchange them */
7243     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7244         AOP_NEEDSACC(left)) {
7245         operand *tmp = right ;
7246         right = left;
7247         left = tmp;
7248     }
7249
7250     /* if result = right then exchange them */
7251     if(pic16_sameRegs(AOP(result),AOP(right))){
7252         operand *tmp = right ;
7253         right = left;
7254         left = tmp;
7255     }
7256
7257     /* if right is bit then exchange them */
7258     if (AOP_TYPE(right) == AOP_CRY &&
7259         AOP_TYPE(left) != AOP_CRY){
7260         operand *tmp = right ;
7261         right = left;
7262         left = tmp;
7263     }
7264
7265     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7266
7267     if(AOP_TYPE(right) == AOP_LIT)
7268         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7269
7270     size = AOP_SIZE(result);
7271
7272     // if(bit | yy)
7273     // xx = bit | yy;
7274     if (AOP_TYPE(left) == AOP_CRY){
7275         if(AOP_TYPE(right) == AOP_LIT){
7276             // c = bit & literal;
7277             if(lit){
7278                 // lit != 0 => result = 1
7279                 if(AOP_TYPE(result) == AOP_CRY){
7280                   if(size)
7281                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7282                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7283                   //     AOP(result)->aopu.aop_dir,
7284                   //     AOP(result)->aopu.aop_dir);
7285                     else if(ifx)
7286                         continueIfTrue(ifx);
7287                     goto release;
7288                 }
7289             } else {
7290                 // lit == 0 => result = left
7291                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7292                     goto release;
7293                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7294             }
7295         } else {
7296             if (AOP_TYPE(right) == AOP_CRY){
7297               if(pic16_sameRegs(AOP(result),AOP(left))){
7298                 // c = bit | bit;
7299                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7300                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7301                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7302
7303                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7304                          AOP(result)->aopu.aop_dir,
7305                          AOP(result)->aopu.aop_dir);
7306                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7307                          AOP(right)->aopu.aop_dir,
7308                          AOP(right)->aopu.aop_dir);
7309                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7310                          AOP(result)->aopu.aop_dir,
7311                          AOP(result)->aopu.aop_dir);
7312               } else {
7313                 if( AOP_TYPE(result) == AOP_ACC) {
7314                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7315                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7316                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7317                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7318
7319                 } else {
7320
7321                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7322                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7323                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7324                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7325
7326                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7327                                  AOP(result)->aopu.aop_dir,
7328                                  AOP(result)->aopu.aop_dir);
7329                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7330                                  AOP(right)->aopu.aop_dir,
7331                                  AOP(right)->aopu.aop_dir);
7332                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7333                                  AOP(left)->aopu.aop_dir,
7334                                  AOP(left)->aopu.aop_dir);
7335                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7336                                  AOP(result)->aopu.aop_dir,
7337                                  AOP(result)->aopu.aop_dir);
7338                 }
7339               }
7340             } else {
7341                 // c = bit | val;
7342                 symbol *tlbl = newiTempLabel(NULL);
7343                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7344
7345
7346                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7347                 if( AOP_TYPE(right) == AOP_ACC) {
7348                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7349                   emitSKPNZ;
7350                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7351                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7352                 }
7353
7354
7355
7356                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7357                     pic16_emitcode(";XXX setb","c");
7358                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7359                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7360                 pic16_toBoolean(right);
7361                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7362                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7363                     jmpTrueOrFalse(ifx, tlbl);
7364                     goto release;
7365                 } else {
7366                     CLRC;
7367                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7368                 }
7369             }
7370         }
7371         // bit = c
7372         // val = c
7373         if(size)
7374             pic16_outBitC(result);
7375         // if(bit | ...)
7376         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7377             genIfxJump(ifx, "c");           
7378         goto release ;
7379     }
7380
7381     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7382     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7383     if((AOP_TYPE(right) == AOP_LIT) &&
7384        (AOP_TYPE(result) == AOP_CRY) &&
7385        (AOP_TYPE(left) != AOP_CRY)){
7386         if(lit){
7387           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7388             // result = 1
7389             if(size)
7390                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7391             else 
7392                 continueIfTrue(ifx);
7393             goto release;
7394         } else {
7395           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7396             // lit = 0, result = boolean(left)
7397             if(size)
7398                 pic16_emitcode(";XXX setb","c");
7399             pic16_toBoolean(right);
7400             if(size){
7401                 symbol *tlbl = newiTempLabel(NULL);
7402                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7403                 CLRC;
7404                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7405             } else {
7406                 genIfxJump (ifx,"a");
7407                 goto release;
7408             }
7409         }
7410         pic16_outBitC(result);
7411         goto release ;
7412     }
7413
7414     /* if left is same as result */
7415     if(pic16_sameRegs(AOP(result),AOP(left))){
7416       int know_W = -1;
7417       for(;size--; offset++,lit>>=8) {
7418         if(AOP_TYPE(right) == AOP_LIT){
7419           if((lit & 0xff) == 0)
7420             /*  or'ing with 0 has no effect */
7421             continue;
7422           else {
7423             int p = my_powof2(lit & 0xff);
7424             if(p>=0) {
7425               /* only one bit is set in the literal, so use a bsf instruction */
7426               pic16_emitpcode(POC_BSF,
7427                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7428             } else {
7429               if(know_W != (lit & 0xff))
7430                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7431               know_W = lit & 0xff;
7432               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7433             }
7434                     
7435           }
7436         } else {
7437           if (AOP_TYPE(left) == AOP_ACC) {
7438             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7439             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7440           } else {                  
7441             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7442             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7443
7444             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7445             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7446
7447           }
7448         }
7449       }
7450     } else {
7451         // left & result in different registers
7452         if(AOP_TYPE(result) == AOP_CRY){
7453             // result = bit
7454             // if(size), result in bit
7455             // if(!size && ifx), conditional oper: if(left | right)
7456             symbol *tlbl = newiTempLabel(NULL);
7457             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7458             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7459
7460
7461             if(size)
7462                 pic16_emitcode(";XXX setb","c");
7463             while(sizer--){
7464                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7465                 pic16_emitcode(";XXX orl","a,%s",
7466                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7467                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7468                 offset++;
7469             }
7470             if(size){
7471                 CLRC;
7472                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7473                 pic16_outBitC(result);
7474             } else if(ifx)
7475                 jmpTrueOrFalse(ifx, tlbl);
7476         } else for(;(size--);offset++){
7477           // normal case
7478           // result = left & right
7479           if(AOP_TYPE(right) == AOP_LIT){
7480             int t = (lit >> (offset*8)) & 0x0FFL;
7481             switch(t) { 
7482             case 0x00:
7483               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7484               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7485
7486               pic16_emitcode("movf","%s,w",
7487                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7488               pic16_emitcode("movwf","%s",
7489                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7490               break;
7491             default:
7492               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7493               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7494               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7495
7496               pic16_emitcode("movlw","0x%x",t);
7497               pic16_emitcode("iorwf","%s,w",
7498                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7499               pic16_emitcode("movwf","%s",
7500                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7501               
7502             }
7503             continue;
7504           }
7505
7506           // faster than result <- left, anl result,right
7507           // and better if result is SFR
7508           if (AOP_TYPE(left) == AOP_ACC) {
7509             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7510             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7511           } else {
7512             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7513             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7514
7515             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7516             pic16_emitcode("iorwf","%s,w",
7517                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7518           }
7519           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7520           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7521         }
7522     }
7523
7524 release :
7525     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7526     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7527     pic16_freeAsmop(result,NULL,ic,TRUE);     
7528 }
7529
7530 /*-----------------------------------------------------------------*/
7531 /* genXor - code for xclusive or                                   */
7532 /*-----------------------------------------------------------------*/
7533 static void genXor (iCode *ic, iCode *ifx)
7534 {
7535   operand *left, *right, *result;
7536   int size, offset=0;
7537   unsigned long lit = 0L;
7538
7539   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7540
7541   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7542   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7543   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7544
7545   /* if left is a literal & right is not ||
7546      if left needs acc & right does not */
7547   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7548       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7549     operand *tmp = right ;
7550     right = left;
7551     left = tmp;
7552   }
7553
7554   /* if result = right then exchange them */
7555   if(pic16_sameRegs(AOP(result),AOP(right))){
7556     operand *tmp = right ;
7557     right = left;
7558     left = tmp;
7559   }
7560
7561   /* if right is bit then exchange them */
7562   if (AOP_TYPE(right) == AOP_CRY &&
7563       AOP_TYPE(left) != AOP_CRY){
7564     operand *tmp = right ;
7565     right = left;
7566     left = tmp;
7567   }
7568   if(AOP_TYPE(right) == AOP_LIT)
7569     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7570
7571   size = AOP_SIZE(result);
7572
7573   // if(bit ^ yy)
7574   // xx = bit ^ yy;
7575   if (AOP_TYPE(left) == AOP_CRY){
7576     if(AOP_TYPE(right) == AOP_LIT){
7577       // c = bit & literal;
7578       if(lit>>1){
7579         // lit>>1  != 0 => result = 1
7580         if(AOP_TYPE(result) == AOP_CRY){
7581           if(size)
7582             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7583             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7584           else if(ifx)
7585             continueIfTrue(ifx);
7586           goto release;
7587         }
7588         pic16_emitcode("setb","c");
7589       } else{
7590         // lit == (0 or 1)
7591         if(lit == 0){
7592           // lit == 0, result = left
7593           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7594             goto release;
7595           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7596         } else{
7597           // lit == 1, result = not(left)
7598           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7599             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7600             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7601             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7602             goto release;
7603           } else {
7604             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7605             pic16_emitcode("cpl","c");
7606           }
7607         }
7608       }
7609
7610     } else {
7611       // right != literal
7612       symbol *tlbl = newiTempLabel(NULL);
7613       if (AOP_TYPE(right) == AOP_CRY){
7614         // c = bit ^ bit;
7615         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7616       }
7617       else{
7618         int sizer = AOP_SIZE(right);
7619         // c = bit ^ val
7620         // if val>>1 != 0, result = 1
7621         pic16_emitcode("setb","c");
7622         while(sizer){
7623           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7624           if(sizer == 1)
7625             // test the msb of the lsb
7626             pic16_emitcode("anl","a,#0xfe");
7627           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7628           sizer--;
7629         }
7630         // val = (0,1)
7631         pic16_emitcode("rrc","a");
7632       }
7633       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7634       pic16_emitcode("cpl","c");
7635       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7636     }
7637     // bit = c
7638     // val = c
7639     if(size)
7640       pic16_outBitC(result);
7641     // if(bit | ...)
7642     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7643       genIfxJump(ifx, "c");           
7644     goto release ;
7645   }
7646
7647   if(pic16_sameRegs(AOP(result),AOP(left))){
7648     /* if left is same as result */
7649     for(;size--; offset++) {
7650       if(AOP_TYPE(right) == AOP_LIT){
7651         int t  = (lit >> (offset*8)) & 0x0FFL;
7652         if(t == 0x00L)
7653           continue;
7654         else
7655           if (IS_AOP_PREG(left)) {
7656             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7658             pic16_aopPut(AOP(result),"a",offset);
7659           } else {
7660             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7661             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7662             pic16_emitcode("xrl","%s,%s",
7663                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7664                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7665           }
7666       } else {
7667         if (AOP_TYPE(left) == AOP_ACC)
7668           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669         else {
7670           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7671           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7672 /*
7673           if (IS_AOP_PREG(left)) {
7674             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7675             pic16_aopPut(AOP(result),"a",offset);
7676           } else
7677             pic16_emitcode("xrl","%s,a",
7678                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7679 */
7680         }
7681       }
7682     }
7683   } else {
7684     // left & result in different registers
7685     if(AOP_TYPE(result) == AOP_CRY){
7686       // result = bit
7687       // if(size), result in bit
7688       // if(!size && ifx), conditional oper: if(left ^ right)
7689       symbol *tlbl = newiTempLabel(NULL);
7690       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7691       if(size)
7692         pic16_emitcode("setb","c");
7693       while(sizer--){
7694         if((AOP_TYPE(right) == AOP_LIT) &&
7695            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7696           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7697         } else {
7698           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7699           pic16_emitcode("xrl","a,%s",
7700                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7701         }
7702         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7703         offset++;
7704       }
7705       if(size){
7706         CLRC;
7707         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7708         pic16_outBitC(result);
7709       } else if(ifx)
7710         jmpTrueOrFalse(ifx, tlbl);
7711     } else for(;(size--);offset++){
7712       // normal case
7713       // result = left & right
7714       if(AOP_TYPE(right) == AOP_LIT){
7715         int t = (lit >> (offset*8)) & 0x0FFL;
7716         switch(t) { 
7717         case 0x00:
7718           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7719           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7720           pic16_emitcode("movf","%s,w",
7721                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7722           pic16_emitcode("movwf","%s",
7723                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7724           break;
7725         case 0xff:
7726           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7727           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7728           pic16_emitcode("comf","%s,w",
7729                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7730           pic16_emitcode("movwf","%s",
7731                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7732           break;
7733         default:
7734           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7735           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7736           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7737           pic16_emitcode("movlw","0x%x",t);
7738           pic16_emitcode("xorwf","%s,w",
7739                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7740           pic16_emitcode("movwf","%s",
7741                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7742
7743         }
7744         continue;
7745       }
7746
7747       // faster than result <- left, anl result,right
7748       // and better if result is SFR
7749       if (AOP_TYPE(left) == AOP_ACC) {
7750         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7751         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7752       } else {
7753         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7754         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7755         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7756         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7757       }
7758       if ( AOP_TYPE(result) != AOP_ACC){
7759         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7760         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7761       }
7762     }
7763   }
7764
7765   release :
7766     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7767   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7768   pic16_freeAsmop(result,NULL,ic,TRUE);     
7769 }
7770
7771 /*-----------------------------------------------------------------*/
7772 /* genInline - write the inline code out                           */
7773 /*-----------------------------------------------------------------*/
7774 static void genInline (iCode *ic)
7775 {
7776   char *buffer, *bp, *bp1;
7777     
7778         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7779
7780         _G.inLine += (!options.asmpeep);
7781
7782         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7783         strcpy(buffer,IC_INLINE(ic));
7784
7785 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7786
7787         /* emit each line as a code */
7788         while (*bp) {
7789                 if (*bp == '\n') {
7790                         *bp++ = '\0';
7791
7792                         if(*bp1)
7793                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7794                         bp1 = bp;
7795                 } else {
7796                         if (*bp == ':') {
7797                                 bp++;
7798                                 *bp = '\0';
7799                                 bp++;
7800
7801                                 /* print label, use this special format with NULL directive
7802                                  * to denote that the argument should not be indented with tab */
7803                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7804                                 bp1 = bp;
7805                         } else
7806                                 bp++;
7807                 }
7808         }
7809
7810         if ((bp1 != bp) && *bp1)
7811                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7812
7813
7814     Safe_free(buffer);
7815
7816     _G.inLine -= (!options.asmpeep);
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* genRRC - rotate right with carry                                */
7821 /*-----------------------------------------------------------------*/
7822 static void genRRC (iCode *ic)
7823 {
7824   operand *left , *result ;
7825   int size, offset = 0, same;
7826
7827   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7828
7829   /* rotate right with carry */
7830   left = IC_LEFT(ic);
7831   result=IC_RESULT(ic);
7832   pic16_aopOp (left,ic,FALSE);
7833   pic16_aopOp (result,ic,FALSE);
7834
7835   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7836
7837   same = pic16_sameRegs(AOP(result),AOP(left));
7838
7839   size = AOP_SIZE(result);    
7840
7841   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7842
7843   /* get the lsb and put it into the carry */
7844   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7845
7846   offset = 0 ;
7847
7848   while(size--) {
7849
7850     if(same) {
7851       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7852     } else {
7853       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7855     }
7856
7857     offset++;
7858   }
7859
7860   pic16_freeAsmop(left,NULL,ic,TRUE);
7861   pic16_freeAsmop(result,NULL,ic,TRUE);
7862 }
7863
7864 /*-----------------------------------------------------------------*/
7865 /* genRLC - generate code for rotate left with carry               */
7866 /*-----------------------------------------------------------------*/
7867 static void genRLC (iCode *ic)
7868 {    
7869   operand *left , *result ;
7870   int size, offset = 0;
7871   int same;
7872
7873   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7874   /* rotate right with carry */
7875   left = IC_LEFT(ic);
7876   result=IC_RESULT(ic);
7877   pic16_aopOp (left,ic,FALSE);
7878   pic16_aopOp (result,ic,FALSE);
7879
7880   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7881
7882   same = pic16_sameRegs(AOP(result),AOP(left));
7883
7884   /* move it to the result */
7885   size = AOP_SIZE(result);    
7886
7887   /* get the msb and put it into the carry */
7888   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7889
7890   offset = 0 ;
7891
7892   while(size--) {
7893
7894     if(same) {
7895       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7896     } else {
7897       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7898       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7899     }
7900
7901     offset++;
7902   }
7903
7904
7905   pic16_freeAsmop(left,NULL,ic,TRUE);
7906   pic16_freeAsmop(result,NULL,ic,TRUE);
7907 }
7908
7909
7910 /* gpasm can get the highest order bit with HIGH/UPPER
7911  * so the following probably is not needed -- VR */
7912  
7913 /*-----------------------------------------------------------------*/
7914 /* genGetHbit - generates code get highest order bit               */
7915 /*-----------------------------------------------------------------*/
7916 static void genGetHbit (iCode *ic)
7917 {
7918     operand *left, *result;
7919     left = IC_LEFT(ic);
7920     result=IC_RESULT(ic);
7921     pic16_aopOp (left,ic,FALSE);
7922     pic16_aopOp (result,ic,FALSE);
7923
7924     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7925     /* get the highest order byte into a */
7926     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7927     if(AOP_TYPE(result) == AOP_CRY){
7928         pic16_emitcode("rlc","a");
7929         pic16_outBitC(result);
7930     }
7931     else{
7932         pic16_emitcode("rl","a");
7933         pic16_emitcode("anl","a,#0x01");
7934         pic16_outAcc(result);
7935     }
7936
7937
7938     pic16_freeAsmop(left,NULL,ic,TRUE);
7939     pic16_freeAsmop(result,NULL,ic,TRUE);
7940 }
7941
7942 #if 0
7943 /*-----------------------------------------------------------------*/
7944 /* AccRol - rotate left accumulator by known count                 */
7945 /*-----------------------------------------------------------------*/
7946 static void AccRol (int shCount)
7947 {
7948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7949     shCount &= 0x0007;              // shCount : 0..7
7950     switch(shCount){
7951         case 0 :
7952             break;
7953         case 1 :
7954             pic16_emitcode("rl","a");
7955             break;
7956         case 2 :
7957             pic16_emitcode("rl","a");
7958             pic16_emitcode("rl","a");
7959             break;
7960         case 3 :
7961             pic16_emitcode("swap","a");
7962             pic16_emitcode("rr","a");
7963             break;
7964         case 4 :
7965             pic16_emitcode("swap","a");
7966             break;
7967         case 5 :
7968             pic16_emitcode("swap","a");
7969             pic16_emitcode("rl","a");
7970             break;
7971         case 6 :
7972             pic16_emitcode("rr","a");
7973             pic16_emitcode("rr","a");
7974             break;
7975         case 7 :
7976             pic16_emitcode("rr","a");
7977             break;
7978     }
7979 }
7980 #endif
7981
7982 /*-----------------------------------------------------------------*/
7983 /* AccLsh - left shift accumulator by known count                  */
7984 /*-----------------------------------------------------------------*/
7985 static void AccLsh (int shCount)
7986 {
7987         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7988         switch(shCount){
7989                 case 0 :
7990                         return;
7991                         break;
7992                 case 1 :
7993                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7994                         break;
7995                 case 2 :
7996                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7997                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7998                         break;
7999                 case 3 :
8000                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8001                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8002                         break;
8003                 case 4 :
8004                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8005                         break;
8006                 case 5 :
8007                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8008                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8009                         break;
8010                 case 6 :
8011                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8012                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8013                         break;
8014                 case 7 :
8015                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8016                         break;
8017         }
8018
8019         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8020 }
8021
8022 /*-----------------------------------------------------------------*/
8023 /* AccRsh - right shift accumulator by known count                 */
8024 /*-----------------------------------------------------------------*/
8025 static void AccRsh (int shCount, int andmask)
8026 {
8027         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8028         switch(shCount){
8029                 case 0 :
8030                         return; break;
8031                 case 1 :
8032                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8033                         break;
8034                 case 2 :
8035                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8036                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8037                         break;
8038                 case 3 :
8039                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8040                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8041                         break;
8042                 case 4 :
8043                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8044                         break;
8045                 case 5 :
8046                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8047                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8048                         break;
8049                 case 6 :
8050                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8051                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8052                         break;
8053                 case 7 :
8054                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8055                         break;
8056         }
8057         
8058         if(andmask)
8059                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8060         else
8061                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8062 }
8063
8064 #if 0
8065 /*-----------------------------------------------------------------*/
8066 /* AccSRsh - signed right shift accumulator by known count                 */
8067 /*-----------------------------------------------------------------*/
8068 static void AccSRsh (int shCount)
8069 {
8070     symbol *tlbl ;
8071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8072     if(shCount != 0){
8073         if(shCount == 1){
8074             pic16_emitcode("mov","c,acc.7");
8075             pic16_emitcode("rrc","a");
8076         } else if(shCount == 2){
8077             pic16_emitcode("mov","c,acc.7");
8078             pic16_emitcode("rrc","a");
8079             pic16_emitcode("mov","c,acc.7");
8080             pic16_emitcode("rrc","a");
8081         } else {
8082             tlbl = newiTempLabel(NULL);
8083             /* rotate right accumulator */
8084             AccRol(8 - shCount);
8085             /* and kill the higher order bits */
8086             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8087             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8088             pic16_emitcode("orl","a,#0x%02x",
8089                      (unsigned char)~SRMask[shCount]);
8090             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8091         }
8092     }
8093 }
8094 #endif
8095
8096 /*-----------------------------------------------------------------*/
8097 /* shiftR1Left2Result - shift right one byte from left to result   */
8098 /*-----------------------------------------------------------------*/
8099 static void shiftR1Left2ResultSigned (operand *left, int offl,
8100                                 operand *result, int offr,
8101                                 int shCount)
8102 {
8103   int same;
8104
8105   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8106
8107   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8108
8109   switch(shCount) {
8110   case 1:
8111     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8112     if(same) 
8113       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8114     else {
8115       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8116       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8117     }
8118
8119     break;
8120   case 2:
8121
8122     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8123     if(same) 
8124       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8125     else {
8126       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8127       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8128     }
8129     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8130     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8131
8132     break;
8133
8134   case 3:
8135     if(same)
8136       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8137     else {
8138       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8139       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8140     }
8141
8142     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8143     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8144     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8145
8146     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8147     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8148
8149     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8150     break;
8151
8152   case 4:
8153     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8154     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8155     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8156     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8157     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8158     break;
8159   case 5:
8160     if(same) {
8161       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8162     } else {
8163       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8164       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8165     }
8166     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8167     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8168     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8169     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8170     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8171     break;
8172
8173   case 6:
8174     if(same) {
8175       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8176       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8177       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8178       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8179       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8180       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8181     } else {
8182       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8183       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8184       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8185       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8186       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8187     }
8188     break;
8189
8190   case 7:
8191     if(same) {
8192       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8193       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8194       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8195       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8196     } else {
8197       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8198       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8199       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8200     }
8201
8202   default:
8203     break;
8204   }
8205 }
8206
8207 /*-----------------------------------------------------------------*/
8208 /* shiftR1Left2Result - shift right one byte from left to result   */
8209 /*-----------------------------------------------------------------*/
8210 static void shiftR1Left2Result (operand *left, int offl,
8211                                 operand *result, int offr,
8212                                 int shCount, int sign)
8213 {
8214   int same;
8215
8216   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8217
8218   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8219
8220   /* Copy the msb into the carry if signed. */
8221   if(sign) {
8222     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8223     return;
8224   }
8225
8226
8227
8228   switch(shCount) {
8229   case 1:
8230     emitCLRC;
8231     if(same) 
8232       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8233     else {
8234       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8235       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8236     }
8237     break;
8238   case 2:
8239     emitCLRC;
8240     if(same) {
8241       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8242     } else {
8243       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8244       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8245     }
8246     emitCLRC;
8247     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8248
8249     break;
8250   case 3:
8251     if(same)
8252       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8253     else {
8254       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8255       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8256     }
8257
8258     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8259     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8260     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8261     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8262     break;
8263       
8264   case 4:
8265     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8266     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8267     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8268     break;
8269
8270   case 5:
8271     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8272     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8273     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8274     //emitCLRC;
8275     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8276
8277     break;
8278   case 6:
8279
8280     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8281     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8282     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8283     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8284     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8285     break;
8286
8287   case 7:
8288
8289     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8290     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8291     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8292
8293     break;
8294
8295   default:
8296     break;
8297   }
8298 }
8299
8300 /*-----------------------------------------------------------------*/
8301 /* shiftL1Left2Result - shift left one byte from left to result    */
8302 /*-----------------------------------------------------------------*/
8303 static void shiftL1Left2Result (operand *left, int offl,
8304                                 operand *result, int offr, int shCount)
8305 {
8306   int same;
8307
8308   //    char *l;
8309   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8310
8311   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8312   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8313     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8314     //    MOVA(l);
8315     /* shift left accumulator */
8316     //AccLsh(shCount); // don't comment out just yet...
8317   //    pic16_aopPut(AOP(result),"a",offr);
8318
8319   switch(shCount) {
8320   case 1:
8321     /* Shift left 1 bit position */
8322     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8323     if(same) {
8324       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8325     } else {
8326       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8327       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8328     }
8329     break;
8330   case 2:
8331     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8332     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8333     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8334     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8335     break;
8336   case 3:
8337     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8338     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8339     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8340     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8341     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8342     break;
8343   case 4:
8344     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8345     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8346     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8347     break;
8348   case 5:
8349     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8350     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8351     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8352     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8353     break;
8354   case 6:
8355     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8356     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8357     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8358     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8359     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8360     break;
8361   case 7:
8362     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8363     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8364     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8365     break;
8366
8367   default:
8368     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8369   }
8370
8371 }
8372
8373 /*-----------------------------------------------------------------*/
8374 /* movLeft2Result - move byte from left to result                  */
8375 /*-----------------------------------------------------------------*/
8376 static void movLeft2Result (operand *left, int offl,
8377                             operand *result, int offr)
8378 {
8379   char *l;
8380   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8381   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8382     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8383
8384     if (*l == '@' && (IS_AOP_PREG(result))) {
8385       pic16_emitcode("mov","a,%s",l);
8386       pic16_aopPut(AOP(result),"a",offr);
8387     } else {
8388       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8389       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8390     }
8391   }
8392 }
8393
8394 /*-----------------------------------------------------------------*/
8395 /* shiftL2Left2Result - shift left two bytes from left to result   */
8396 /*-----------------------------------------------------------------*/
8397 static void shiftL2Left2Result (operand *left, int offl,
8398                                 operand *result, int offr, int shCount)
8399 {
8400   int same = pic16_sameRegs(AOP(result), AOP(left));
8401   int i;
8402
8403   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8404
8405   if (same && (offl != offr)) { // shift bytes
8406     if (offr > offl) {
8407        for(i=1;i>-1;i--) {
8408          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8409          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8410        }
8411     } else { // just treat as different later on
8412                 same = 0;
8413     }
8414   }
8415
8416   if(same) {
8417     switch(shCount) {
8418     case 0:
8419       break;
8420     case 1:
8421     case 2:
8422     case 3:
8423
8424       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8425       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8426       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8427
8428       while(--shCount) {
8429                 emitCLRC;
8430                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8431                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8432       }
8433
8434       break;
8435     case 4:
8436     case 5:
8437       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8438       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8439       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8440       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8441       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8442       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8443       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8444       if(shCount >=5) {
8445                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8446                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8447       }
8448       break;
8449     case 6:
8450       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8451       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8452       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8453       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8454       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8455       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8456       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8457       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8458       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8459       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8460       break;
8461     case 7:
8462       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8463       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8464       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8465       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8466       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8467     }
8468
8469   } else {
8470     switch(shCount) {
8471     case 0:
8472       break;
8473     case 1:
8474     case 2:
8475     case 3:
8476       /* note, use a mov/add for the shift since the mov has a
8477          chance of getting optimized out */
8478       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8479       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8480       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8481       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8482       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8483
8484       while(--shCount) {
8485                 emitCLRC;
8486                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8487                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8488       }
8489       break;
8490
8491     case 4:
8492     case 5:
8493       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8494       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8495       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8496       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8497       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8498       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8499       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8500       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8501
8502
8503       if(shCount == 5) {
8504                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8505                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8506       }
8507       break;
8508     case 6:
8509       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8510       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8511       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8512       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8513
8514       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8515       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8516       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8517       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8518       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8519       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8520       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8521       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8522       break;
8523     case 7:
8524       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8525       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8526       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8527       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8528       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8529     }
8530   }
8531
8532 }
8533 /*-----------------------------------------------------------------*/
8534 /* shiftR2Left2Result - shift right two bytes from left to result  */
8535 /*-----------------------------------------------------------------*/
8536 static void shiftR2Left2Result (operand *left, int offl,
8537                                 operand *result, int offr,
8538                                 int shCount, int sign)
8539 {
8540   int same = pic16_sameRegs(AOP(result), AOP(left));
8541   int i;
8542   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8543
8544   if (same && (offl != offr)) { // shift right bytes
8545     if (offr < offl) {
8546        for(i=0;i<2;i++) {
8547          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8548          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8549        }
8550     } else { // just treat as different later on
8551                 same = 0;
8552     }
8553   }
8554
8555   switch(shCount) {
8556   case 0:
8557     break;
8558   case 1:
8559   case 2:
8560   case 3:
8561     if(sign)
8562       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8563     else
8564       emitCLRC;
8565
8566     if(same) {
8567       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8568       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8569     } else {
8570       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8571       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8572       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8573       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8574     }
8575
8576     while(--shCount) {
8577       if(sign)
8578                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8579       else
8580                 emitCLRC;
8581       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8582       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8583     }
8584     break;
8585   case 4:
8586   case 5:
8587     if(same) {
8588
8589       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8590       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8591       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8592
8593       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8594       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8595       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8596       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8597     } else {
8598       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8599       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8600       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8601
8602       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8603       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8604       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8605       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8606       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8607     }
8608
8609     if(shCount >=5) {
8610       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8611       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8612     }
8613
8614     if(sign) {
8615       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8616       pic16_emitpcode(POC_BTFSC, 
8617                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8618       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8619     }
8620
8621     break;
8622
8623   case 6:
8624     if(same) {
8625
8626       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8627       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8628
8629       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8630       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8631       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8632       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8633       if(sign) {
8634         pic16_emitpcode(POC_BTFSC, 
8635                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8636         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8637       }
8638       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8639       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8640       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8641       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8642     } else {
8643       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8644       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8645       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8646       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8647       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8648       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8649       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8650       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8651       if(sign) {
8652         pic16_emitpcode(POC_BTFSC, 
8653                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8654         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8655       }
8656       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8657       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8658
8659         
8660     }
8661
8662     break;
8663   case 7:
8664     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8665     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8666     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8667     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8668     if(sign) {
8669       emitSKPNC;
8670       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8671     } else 
8672       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8673   }
8674 }
8675
8676
8677 /*-----------------------------------------------------------------*/
8678 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8679 /*-----------------------------------------------------------------*/
8680 static void shiftLLeftOrResult (operand *left, int offl,
8681                                 operand *result, int offr, int shCount)
8682 {
8683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8684
8685     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8686     /* shift left accumulator */
8687     AccLsh(shCount);
8688     /* or with result */
8689     /* back to result */
8690     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8691 }
8692
8693 /*-----------------------------------------------------------------*/
8694 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8695 /*-----------------------------------------------------------------*/
8696 static void shiftRLeftOrResult (operand *left, int offl,
8697                                 operand *result, int offr, int shCount)
8698 {
8699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8700     
8701     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8702     /* shift right accumulator */
8703     AccRsh(shCount, 1);
8704     /* or with result */
8705     /* back to result */
8706     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8707 }
8708
8709 /*-----------------------------------------------------------------*/
8710 /* genlshOne - left shift a one byte quantity by known count       */
8711 /*-----------------------------------------------------------------*/
8712 static void genlshOne (operand *result, operand *left, int shCount)
8713 {       
8714     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8715     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8716 }
8717
8718 /*-----------------------------------------------------------------*/
8719 /* genlshTwo - left shift two bytes by known amount != 0           */
8720 /*-----------------------------------------------------------------*/
8721 static void genlshTwo (operand *result,operand *left, int shCount)
8722 {
8723     int size;
8724     
8725     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8726     size = pic16_getDataSize(result);
8727
8728     /* if shCount >= 8 */
8729     if (shCount >= 8) {
8730         shCount -= 8 ;
8731
8732         if (size > 1){
8733             if (shCount)
8734                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8735             else 
8736                 movLeft2Result(left, LSB, result, MSB16);
8737         }
8738         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8739     }
8740
8741     /*  1 <= shCount <= 7 */
8742     else {  
8743         if(size == 1)
8744             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8745         else 
8746             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8747     }
8748 }
8749
8750 /*-----------------------------------------------------------------*/
8751 /* shiftLLong - shift left one long from left to result            */
8752 /* offr = LSB or MSB16                                             */
8753 /*-----------------------------------------------------------------*/
8754 static void shiftLLong (operand *left, operand *result, int offr )
8755 {
8756     int size = AOP_SIZE(result);
8757     int same = pic16_sameRegs(AOP(left),AOP(result));
8758         int i;
8759
8760     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8761
8762         if (same && (offr == MSB16)) { //shift one byte
8763                 for(i=size-1;i>=MSB16;i--) {
8764                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8765                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8766                 }
8767         } else {
8768                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8769         }
8770         
8771     if (size > LSB+offr ){
8772                 if (same) {
8773                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8774                 } else {
8775                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8776                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8777                 }
8778          }
8779
8780     if(size > MSB16+offr){
8781                 if (same) {
8782                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8783                 } else {
8784                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8785                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8786                 }
8787     }
8788
8789     if(size > MSB24+offr){
8790                 if (same) {
8791                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8792                 } else {
8793                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8794                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8795                 }
8796     }
8797
8798     if(size > MSB32+offr){
8799                 if (same) {
8800                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8801                 } else {
8802                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8803                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8804                 }
8805     }
8806     if(offr != LSB)
8807                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8808
8809 }
8810
8811 /*-----------------------------------------------------------------*/
8812 /* genlshFour - shift four byte by a known amount != 0             */
8813 /*-----------------------------------------------------------------*/
8814 static void genlshFour (operand *result, operand *left, int shCount)
8815 {
8816     int size;
8817
8818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8819     size = AOP_SIZE(result);
8820
8821     /* if shifting more that 3 bytes */
8822     if (shCount >= 24 ) {
8823         shCount -= 24;
8824         if (shCount)
8825             /* lowest order of left goes to the highest
8826             order of the destination */
8827             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8828         else
8829             movLeft2Result(left, LSB, result, MSB32);
8830
8831                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8832                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8833                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8834
8835         return;
8836     }
8837
8838     /* more than two bytes */
8839     else if ( shCount >= 16 ) {
8840         /* lower order two bytes goes to higher order two bytes */
8841         shCount -= 16;
8842         /* if some more remaining */
8843         if (shCount)
8844             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8845         else {
8846             movLeft2Result(left, MSB16, result, MSB32);
8847             movLeft2Result(left, LSB, result, MSB24);
8848         }
8849                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8850                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8851         return;
8852     }    
8853
8854     /* if more than 1 byte */
8855     else if ( shCount >= 8 ) {
8856         /* lower order three bytes goes to higher order  three bytes */
8857         shCount -= 8;
8858         if(size == 2){
8859             if(shCount)
8860                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8861             else
8862                 movLeft2Result(left, LSB, result, MSB16);
8863         }
8864         else{   /* size = 4 */
8865             if(shCount == 0){
8866                 movLeft2Result(left, MSB24, result, MSB32);
8867                 movLeft2Result(left, MSB16, result, MSB24);
8868                 movLeft2Result(left, LSB, result, MSB16);
8869                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8870             }
8871             else if(shCount == 1)
8872                 shiftLLong(left, result, MSB16);
8873             else{
8874                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8875                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8876                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8877                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8878             }
8879         }
8880     }
8881
8882     /* 1 <= shCount <= 7 */
8883     else if(shCount <= 3)
8884     { 
8885         shiftLLong(left, result, LSB);
8886         while(--shCount >= 1)
8887             shiftLLong(result, result, LSB);
8888     }
8889     /* 3 <= shCount <= 7, optimize */
8890     else{
8891         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8892         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8893         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8894     }
8895 }
8896
8897 /*-----------------------------------------------------------------*/
8898 /* genLeftShiftLiteral - left shifting by known count              */
8899 /*-----------------------------------------------------------------*/
8900 static void genLeftShiftLiteral (operand *left,
8901                                  operand *right,
8902                                  operand *result,
8903                                  iCode *ic)
8904 {    
8905     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8906     int size;
8907
8908     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8909     pic16_freeAsmop(right,NULL,ic,TRUE);
8910
8911     pic16_aopOp(left,ic,FALSE);
8912     pic16_aopOp(result,ic,FALSE);
8913
8914     size = getSize(operandType(result));
8915
8916 #if VIEW_SIZE
8917     pic16_emitcode("; shift left ","result %d, left %d",size,
8918              AOP_SIZE(left));
8919 #endif
8920
8921     /* I suppose that the left size >= result size */
8922     if(shCount == 0){
8923         while(size--){
8924             movLeft2Result(left, size, result, size);
8925         }
8926     }
8927
8928     else if(shCount >= (size * 8))
8929         while(size--)
8930             pic16_aopPut(AOP(result),zero,size);
8931     else{
8932         switch (size) {
8933             case 1:
8934                 genlshOne (result,left,shCount);
8935                 break;
8936
8937             case 2:
8938             case 3:
8939                 genlshTwo (result,left,shCount);
8940                 break;
8941
8942             case 4:
8943                 genlshFour (result,left,shCount);
8944                 break;
8945         }
8946     }
8947     pic16_freeAsmop(left,NULL,ic,TRUE);
8948     pic16_freeAsmop(result,NULL,ic,TRUE);
8949 }
8950
8951 /*-----------------------------------------------------------------*
8952  * genMultiAsm - repeat assembly instruction for size of register.
8953  * if endian == 1, then the high byte (i.e base address + size of 
8954  * register) is used first else the low byte is used first;
8955  *-----------------------------------------------------------------*/
8956 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8957 {
8958
8959   int offset = 0;
8960
8961   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8962
8963   if(!reg)
8964     return;
8965
8966   if(!endian) {
8967     endian = 1;
8968   } else {
8969     endian = -1;
8970     offset = size-1;
8971   }
8972
8973   while(size--) {
8974     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8975     offset += endian;
8976   }
8977
8978 }
8979 /*-----------------------------------------------------------------*/
8980 /* genLeftShift - generates code for left shifting                 */
8981 /*-----------------------------------------------------------------*/
8982 static void genLeftShift (iCode *ic)
8983 {
8984   operand *left,*right, *result;
8985   int size, offset;
8986 //  char *l;
8987   symbol *tlbl , *tlbl1;
8988   pCodeOp *pctemp;
8989
8990   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8991
8992   right = IC_RIGHT(ic);
8993   left  = IC_LEFT(ic);
8994   result = IC_RESULT(ic);
8995
8996   pic16_aopOp(right,ic,FALSE);
8997
8998   /* if the shift count is known then do it 
8999      as efficiently as possible */
9000   if (AOP_TYPE(right) == AOP_LIT) {
9001     genLeftShiftLiteral (left,right,result,ic);
9002     return ;
9003   }
9004
9005   /* shift count is unknown then we have to form
9006    * a loop. Get the loop count in WREG : Note: we take
9007    * only the lower order byte since shifting
9008    * more than 32 bits make no sense anyway, ( the
9009    * largest size of an object can be only 32 bits ) */
9010   
9011   pic16_aopOp(left,ic,FALSE);
9012   pic16_aopOp(result,ic,FALSE);
9013
9014   /* now move the left to the result if they are not the
9015    * same, and if size > 1,
9016    * and if right is not same to result (!!!) -- VR */
9017   if (!pic16_sameRegs(AOP(left),AOP(result))
9018       && (AOP_SIZE(result) > 1)) {
9019
9020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9021
9022     size = AOP_SIZE(result);
9023     offset=0;
9024     while (size--) {
9025
9026 #if 0
9027       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9028       if (*l == '@' && (IS_AOP_PREG(result))) {
9029
9030           pic16_emitcode("mov","a,%s",l);
9031           pic16_aopPut(AOP(result),"a",offset);
9032       } else
9033 #endif
9034       {
9035         /* we don't know if left is a literal or a register, take care -- VR */
9036         mov2f(AOP(result), AOP(left), offset);
9037       }
9038       offset++;
9039     }
9040   }
9041
9042   size = AOP_SIZE(result);
9043
9044   /* if it is only one byte then */
9045   if (size == 1) {
9046     if(optimized_for_speed) {
9047       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9048       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9049       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9050       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9051       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9052       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9053       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9054       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9055       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9056       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9057       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9058       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9059     } else {
9060
9061       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9062
9063       tlbl = newiTempLabel(NULL);
9064
9065 #if 1
9066       /* this is already done, why change it? */
9067       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9068                 mov2f(AOP(result), AOP(left), 0);
9069       }
9070 #endif
9071
9072       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9073       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9074       pic16_emitpLabel(tlbl->key);
9075       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9076       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9077       emitSKPC;
9078       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9079     }
9080     goto release ;
9081   }
9082     
9083   if (pic16_sameRegs(AOP(left),AOP(result))) {
9084
9085     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9086     
9087     tlbl = newiTempLabel(NULL);
9088     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9089     genMultiAsm(POC_RRCF, result, size,1);
9090     pic16_emitpLabel(tlbl->key);
9091     genMultiAsm(POC_RLCF, result, size,0);
9092     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9093     emitSKPC;
9094     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9095     goto release;
9096   }
9097
9098   //tlbl = newiTempLabel(NULL);
9099   //offset = 0 ;   
9100   //tlbl1 = newiTempLabel(NULL);
9101
9102   //reAdjustPreg(AOP(result));    
9103     
9104   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9105   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9106   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9107   //MOVA(l);
9108   //pic16_emitcode("add","a,acc");         
9109   //pic16_aopPut(AOP(result),"a",offset++);
9110   //while (--size) {
9111   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9112   //  MOVA(l);
9113   //  pic16_emitcode("rlc","a");         
9114   //  pic16_aopPut(AOP(result),"a",offset++);
9115   //}
9116   //reAdjustPreg(AOP(result));
9117
9118   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9119   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9120
9121
9122   tlbl = newiTempLabel(NULL);
9123   tlbl1= newiTempLabel(NULL);
9124
9125   size = AOP_SIZE(result);
9126   offset = 1;
9127
9128   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9129
9130   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9131
9132   /* offset should be 0, 1 or 3 */
9133   
9134   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9135   emitSKPNZ;
9136   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9137
9138   pic16_emitpcode(POC_MOVWF, pctemp);
9139
9140
9141   pic16_emitpLabel(tlbl->key);
9142
9143   emitCLRC;
9144   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9145   while(--size)
9146     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9147
9148   pic16_emitpcode(POC_DECFSZ,  pctemp);
9149   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9150   pic16_emitpLabel(tlbl1->key);
9151
9152   pic16_popReleaseTempReg(pctemp,1);
9153
9154
9155  release:
9156   pic16_freeAsmop (right,NULL,ic,TRUE);
9157   pic16_freeAsmop(left,NULL,ic,TRUE);
9158   pic16_freeAsmop(result,NULL,ic,TRUE);
9159 }
9160
9161
9162
9163 #if 0
9164 #error old code (left here for reference)
9165 /*-----------------------------------------------------------------*/
9166 /* genLeftShift - generates code for left shifting                 */
9167 /*-----------------------------------------------------------------*/
9168 static void genLeftShift (iCode *ic)
9169 {
9170   operand *left,*right, *result;
9171   int size, offset;
9172   char *l;
9173   symbol *tlbl , *tlbl1;
9174   pCodeOp *pctemp;
9175
9176   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9177
9178   right = IC_RIGHT(ic);
9179   left  = IC_LEFT(ic);
9180   result = IC_RESULT(ic);
9181
9182   pic16_aopOp(right,ic,FALSE);
9183
9184   /* if the shift count is known then do it 
9185      as efficiently as possible */
9186   if (AOP_TYPE(right) == AOP_LIT) {
9187     genLeftShiftLiteral (left,right,result,ic);
9188     return ;
9189   }
9190
9191   /* shift count is unknown then we have to form 
9192      a loop get the loop count in B : Note: we take
9193      only the lower order byte since shifting
9194      more that 32 bits make no sense anyway, ( the
9195      largest size of an object can be only 32 bits ) */  
9196
9197     
9198   pic16_aopOp(left,ic,FALSE);
9199   pic16_aopOp(result,ic,FALSE);
9200
9201   /* now move the left to the result if they are not the
9202      same */
9203   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9204       AOP_SIZE(result) > 1) {
9205
9206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9207
9208     size = AOP_SIZE(result);
9209     offset=0;
9210     while (size--) {
9211       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9212       if (*l == '@' && (IS_AOP_PREG(result))) {
9213
9214         pic16_emitcode("mov","a,%s",l);
9215         pic16_aopPut(AOP(result),"a",offset);
9216       } else {
9217
9218         /* we don't know if left is a literal or a register, take care -- VR */
9219         mov2f(AOP(result), AOP(left), offset);
9220       }
9221       offset++;
9222     }
9223   }
9224
9225   size = AOP_SIZE(result);
9226
9227   /* if it is only one byte then */
9228   if (size == 1) {
9229     if(optimized_for_speed) {
9230       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9231       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9232       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9233       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9234       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9235       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9236       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9237       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9238       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9239       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9240       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9241       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9242     } else {
9243
9244       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9245
9246       tlbl = newiTempLabel(NULL);
9247       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9248                 mov2f(AOP(result), AOP(left), 0);
9249                 
9250 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9251 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9252       }
9253
9254       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9255       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9256       pic16_emitpLabel(tlbl->key);
9257       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9258       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9259       emitSKPC;
9260       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9261     }
9262     goto release ;
9263   }
9264     
9265   if (pic16_sameRegs(AOP(left),AOP(result))) {
9266
9267     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9268     
9269     tlbl = newiTempLabel(NULL);
9270     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9271     genMultiAsm(POC_RRCF, result, size,1);
9272     pic16_emitpLabel(tlbl->key);
9273     genMultiAsm(POC_RLCF, result, size,0);
9274     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9275     emitSKPC;
9276     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9277     goto release;
9278   }
9279
9280   //tlbl = newiTempLabel(NULL);
9281   //offset = 0 ;   
9282   //tlbl1 = newiTempLabel(NULL);
9283
9284   //reAdjustPreg(AOP(result));    
9285     
9286   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9287   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9288   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9289   //MOVA(l);
9290   //pic16_emitcode("add","a,acc");         
9291   //pic16_aopPut(AOP(result),"a",offset++);
9292   //while (--size) {
9293   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9294   //  MOVA(l);
9295   //  pic16_emitcode("rlc","a");         
9296   //  pic16_aopPut(AOP(result),"a",offset++);
9297   //}
9298   //reAdjustPreg(AOP(result));
9299
9300   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9301   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9302
9303
9304   tlbl = newiTempLabel(NULL);
9305   tlbl1= newiTempLabel(NULL);
9306
9307   size = AOP_SIZE(result);
9308   offset = 1;
9309
9310   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9311
9312   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9313
9314   /* offset should be 0, 1 or 3 */
9315   
9316   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9317   emitSKPNZ;
9318   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9319
9320   pic16_emitpcode(POC_MOVWF, pctemp);
9321
9322
9323   pic16_emitpLabel(tlbl->key);
9324
9325   emitCLRC;
9326   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9327   while(--size)
9328     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9329
9330   pic16_emitpcode(POC_DECFSZ,  pctemp);
9331   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9332   pic16_emitpLabel(tlbl1->key);
9333
9334   pic16_popReleaseTempReg(pctemp,1);
9335
9336
9337  release:
9338   pic16_freeAsmop (right,NULL,ic,TRUE);
9339   pic16_freeAsmop(left,NULL,ic,TRUE);
9340   pic16_freeAsmop(result,NULL,ic,TRUE);
9341 }
9342 #endif
9343
9344 /*-----------------------------------------------------------------*/
9345 /* genrshOne - right shift a one byte quantity by known count      */
9346 /*-----------------------------------------------------------------*/
9347 static void genrshOne (operand *result, operand *left,
9348                        int shCount, int sign)
9349 {
9350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9351     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9352 }
9353
9354 /*-----------------------------------------------------------------*/
9355 /* genrshTwo - right shift two bytes by known amount != 0          */
9356 /*-----------------------------------------------------------------*/
9357 static void genrshTwo (operand *result,operand *left,
9358                        int shCount, int sign)
9359 {
9360   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9361   /* if shCount >= 8 */
9362   if (shCount >= 8) {
9363     shCount -= 8 ;
9364     if (shCount)
9365       shiftR1Left2Result(left, MSB16, result, LSB,
9366                          shCount, sign);
9367     else
9368       movLeft2Result(left, MSB16, result, LSB);
9369
9370     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9371
9372     if(sign) {
9373       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9374       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9375     }
9376   }
9377
9378   /*  1 <= shCount <= 7 */
9379   else
9380     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9381 }
9382
9383 /*-----------------------------------------------------------------*/
9384 /* shiftRLong - shift right one long from left to result           */
9385 /* offl = LSB or MSB16                                             */
9386 /*-----------------------------------------------------------------*/
9387 static void shiftRLong (operand *left, int offl,
9388                         operand *result, int sign)
9389 {
9390     int size = AOP_SIZE(result);
9391     int same = pic16_sameRegs(AOP(left),AOP(result));
9392     int i;
9393     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9394
9395         if (same && (offl == MSB16)) { //shift one byte right
9396                 for(i=MSB16;i<size;i++) {
9397                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9398                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9399                 }
9400         }
9401
9402     if(sign)
9403                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9404         else
9405                 emitCLRC;
9406
9407         if (same) {
9408                 if (offl == LSB)
9409                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9410         } else {
9411         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9412         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9413         }
9414
9415     if(offl == MSB16) {
9416         /* add sign of "a" */
9417         pic16_addSign(result, MSB32, sign);
9418         }
9419
9420         if (same) {
9421         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9422         } else {
9423         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9424         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9425         }
9426         
9427         if (same) {
9428         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9429         } else {
9430         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9431         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9432         }
9433
9434         if (same) {
9435         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9436         } else {
9437         if(offl == LSB){
9438                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9439                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9440         }
9441         }
9442 }
9443
9444 /*-----------------------------------------------------------------*/
9445 /* genrshFour - shift four byte by a known amount != 0             */
9446 /*-----------------------------------------------------------------*/
9447 static void genrshFour (operand *result, operand *left,
9448                         int shCount, int sign)
9449 {
9450   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9451   /* if shifting more that 3 bytes */
9452   if(shCount >= 24 ) {
9453     shCount -= 24;
9454     if(shCount)
9455       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9456     else
9457       movLeft2Result(left, MSB32, result, LSB);
9458
9459     pic16_addSign(result, MSB16, sign);
9460   }
9461   else if(shCount >= 16){
9462     shCount -= 16;
9463     if(shCount)
9464       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9465     else{
9466       movLeft2Result(left, MSB24, result, LSB);
9467       movLeft2Result(left, MSB32, result, MSB16);
9468     }
9469     pic16_addSign(result, MSB24, sign);
9470   }
9471   else if(shCount >= 8){
9472     shCount -= 8;
9473     if(shCount == 1)
9474       shiftRLong(left, MSB16, result, sign);
9475     else if(shCount == 0){
9476       movLeft2Result(left, MSB16, result, LSB);
9477       movLeft2Result(left, MSB24, result, MSB16);
9478       movLeft2Result(left, MSB32, result, MSB24);
9479       pic16_addSign(result, MSB32, sign);
9480     }
9481     else{ //shcount >= 2
9482       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9483       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9484       /* the last shift is signed */
9485       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9486       pic16_addSign(result, MSB32, sign);
9487     }
9488   }
9489   else{   /* 1 <= shCount <= 7 */
9490     if(shCount <= 2){
9491       shiftRLong(left, LSB, result, sign);
9492       if(shCount == 2)
9493         shiftRLong(result, LSB, result, sign);
9494     }
9495     else{
9496       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9497       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9498       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9499     }
9500   }
9501 }
9502
9503 /*-----------------------------------------------------------------*/
9504 /* genRightShiftLiteral - right shifting by known count            */
9505 /*-----------------------------------------------------------------*/
9506 static void genRightShiftLiteral (operand *left,
9507                                   operand *right,
9508                                   operand *result,
9509                                   iCode *ic,
9510                                   int sign)
9511 {    
9512   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9513   int lsize,res_size;
9514
9515   pic16_freeAsmop(right,NULL,ic,TRUE);
9516
9517   pic16_aopOp(left,ic,FALSE);
9518   pic16_aopOp(result,ic,FALSE);
9519
9520   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9521
9522 #if VIEW_SIZE
9523   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9524                  AOP_SIZE(left));
9525 #endif
9526
9527   lsize = pic16_getDataSize(left);
9528   res_size = pic16_getDataSize(result);
9529   /* test the LEFT size !!! */
9530
9531   /* I suppose that the left size >= result size */
9532   if(shCount == 0){
9533     while(res_size--)
9534       movLeft2Result(left, lsize, result, res_size);
9535   }
9536
9537   else if(shCount >= (lsize * 8)){
9538
9539     if(res_size == 1) {
9540       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9541       if(sign) {
9542         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9543         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9544       }
9545     } else {
9546
9547       if(sign) {
9548         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9549         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9550         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9551         while(res_size--)
9552           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9553
9554       } else {
9555
9556         while(res_size--)
9557           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9558       }
9559     }
9560   } else {
9561
9562     switch (res_size) {
9563     case 1:
9564       genrshOne (result,left,shCount,sign);
9565       break;
9566
9567     case 2:
9568       genrshTwo (result,left,shCount,sign);
9569       break;
9570
9571     case 4:
9572       genrshFour (result,left,shCount,sign);
9573       break;
9574     default :
9575       break;
9576     }
9577
9578   }
9579
9580   pic16_freeAsmop(left,NULL,ic,TRUE);
9581   pic16_freeAsmop(result,NULL,ic,TRUE);
9582 }
9583
9584 /*-----------------------------------------------------------------*/
9585 /* genSignedRightShift - right shift of signed number              */
9586 /*-----------------------------------------------------------------*/
9587 static void genSignedRightShift (iCode *ic)
9588 {
9589   operand *right, *left, *result;
9590   int size, offset;
9591   //  char *l;
9592   symbol *tlbl, *tlbl1 ;
9593   pCodeOp *pctemp;
9594
9595   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9596
9597   /* we do it the hard way put the shift count in b
9598      and loop thru preserving the sign */
9599   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9600
9601   right = IC_RIGHT(ic);
9602   left  = IC_LEFT(ic);
9603   result = IC_RESULT(ic);
9604
9605   pic16_aopOp(right,ic,FALSE);  
9606   pic16_aopOp(left,ic,FALSE);
9607   pic16_aopOp(result,ic,FALSE);
9608
9609
9610   if ( AOP_TYPE(right) == AOP_LIT) {
9611     genRightShiftLiteral (left,right,result,ic,1);
9612     return ;
9613   }
9614   /* shift count is unknown then we have to form 
9615      a loop get the loop count in B : Note: we take
9616      only the lower order byte since shifting
9617      more that 32 bits make no sense anyway, ( the
9618      largest size of an object can be only 32 bits ) */  
9619
9620   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9621   //pic16_emitcode("inc","b");
9622   //pic16_freeAsmop (right,NULL,ic,TRUE);
9623   //pic16_aopOp(left,ic,FALSE);
9624   //pic16_aopOp(result,ic,FALSE);
9625
9626   /* now move the left to the result if they are not the
9627      same */
9628   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9629       AOP_SIZE(result) > 1) {
9630
9631     size = AOP_SIZE(result);
9632     offset=0;
9633     while (size--) { 
9634       /*
9635         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9636         if (*l == '@' && IS_AOP_PREG(result)) {
9637
9638         pic16_emitcode("mov","a,%s",l);
9639         pic16_aopPut(AOP(result),"a",offset);
9640         } else
9641         pic16_aopPut(AOP(result),l,offset);
9642       */
9643       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9644       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9645
9646       offset++;
9647     }
9648   }
9649
9650   /* mov the highest order bit to OVR */    
9651   tlbl = newiTempLabel(NULL);
9652   tlbl1= newiTempLabel(NULL);
9653
9654   size = AOP_SIZE(result);
9655   offset = size - 1;
9656
9657   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9658
9659   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9660
9661   /* offset should be 0, 1 or 3 */
9662   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9663   emitSKPNZ;
9664   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9665
9666   pic16_emitpcode(POC_MOVWF, pctemp);
9667
9668
9669   pic16_emitpLabel(tlbl->key);
9670
9671   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9672   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9673
9674   while(--size) {
9675     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9676   }
9677
9678   pic16_emitpcode(POC_DECFSZ,  pctemp);
9679   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9680   pic16_emitpLabel(tlbl1->key);
9681
9682   pic16_popReleaseTempReg(pctemp,1);
9683 #if 0
9684   size = AOP_SIZE(result);
9685   offset = size - 1;
9686   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9687   pic16_emitcode("rlc","a");
9688   pic16_emitcode("mov","ov,c");
9689   /* if it is only one byte then */
9690   if (size == 1) {
9691     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9692     MOVA(l);
9693     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9694     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9695     pic16_emitcode("mov","c,ov");
9696     pic16_emitcode("rrc","a");
9697     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9698     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9699     pic16_aopPut(AOP(result),"a",0);
9700     goto release ;
9701   }
9702
9703   reAdjustPreg(AOP(result));
9704   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9705   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9706   pic16_emitcode("mov","c,ov");
9707   while (size--) {
9708     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9709     MOVA(l);
9710     pic16_emitcode("rrc","a");         
9711     pic16_aopPut(AOP(result),"a",offset--);
9712   }
9713   reAdjustPreg(AOP(result));
9714   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9715   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9716
9717  release:
9718 #endif
9719
9720   pic16_freeAsmop(left,NULL,ic,TRUE);
9721   pic16_freeAsmop(result,NULL,ic,TRUE);
9722   pic16_freeAsmop(right,NULL,ic,TRUE);
9723 }
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genRightShift - generate code for right shifting                */
9727 /*-----------------------------------------------------------------*/
9728 static void genRightShift (iCode *ic)
9729 {
9730     operand *right, *left, *result;
9731     sym_link *letype ;
9732     int size, offset;
9733     char *l;
9734     symbol *tlbl, *tlbl1 ;
9735
9736     /* if signed then we do it the hard way preserve the
9737     sign bit moving it inwards */
9738     letype = getSpec(operandType(IC_LEFT(ic)));
9739     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9740
9741     if (!SPEC_USIGN(letype)) {
9742         genSignedRightShift (ic);
9743         return ;
9744     }
9745
9746     /* signed & unsigned types are treated the same : i.e. the
9747     signed is NOT propagated inwards : quoting from the
9748     ANSI - standard : "for E1 >> E2, is equivalent to division
9749     by 2**E2 if unsigned or if it has a non-negative value,
9750     otherwise the result is implementation defined ", MY definition
9751     is that the sign does not get propagated */
9752
9753     right = IC_RIGHT(ic);
9754     left  = IC_LEFT(ic);
9755     result = IC_RESULT(ic);
9756
9757     pic16_aopOp(right,ic,FALSE);
9758
9759     /* if the shift count is known then do it 
9760     as efficiently as possible */
9761     if (AOP_TYPE(right) == AOP_LIT) {
9762         genRightShiftLiteral (left,right,result,ic, 0);
9763         return ;
9764     }
9765
9766     /* shift count is unknown then we have to form 
9767     a loop get the loop count in B : Note: we take
9768     only the lower order byte since shifting
9769     more that 32 bits make no sense anyway, ( the
9770     largest size of an object can be only 32 bits ) */  
9771
9772     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9773     pic16_emitcode("inc","b");
9774     pic16_aopOp(left,ic,FALSE);
9775     pic16_aopOp(result,ic,FALSE);
9776
9777     /* now move the left to the result if they are not the
9778     same */
9779     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9780         AOP_SIZE(result) > 1) {
9781
9782         size = AOP_SIZE(result);
9783         offset=0;
9784         while (size--) {
9785             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9786             if (*l == '@' && IS_AOP_PREG(result)) {
9787
9788                 pic16_emitcode("mov","a,%s",l);
9789                 pic16_aopPut(AOP(result),"a",offset);
9790             } else
9791                 pic16_aopPut(AOP(result),l,offset);
9792             offset++;
9793         }
9794     }
9795
9796     tlbl = newiTempLabel(NULL);
9797     tlbl1= newiTempLabel(NULL);
9798     size = AOP_SIZE(result);
9799     offset = size - 1;
9800
9801     /* if it is only one byte then */
9802     if (size == 1) {
9803
9804       tlbl = newiTempLabel(NULL);
9805       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9806         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9807         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9808       }
9809
9810       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9811       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9812       pic16_emitpLabel(tlbl->key);
9813       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9814       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9815       emitSKPC;
9816       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9817
9818       goto release ;
9819     }
9820
9821     reAdjustPreg(AOP(result));
9822     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9823     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9824     CLRC;
9825     while (size--) {
9826         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9827         MOVA(l);
9828         pic16_emitcode("rrc","a");         
9829         pic16_aopPut(AOP(result),"a",offset--);
9830     }
9831     reAdjustPreg(AOP(result));
9832
9833     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9834     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9835
9836 release:
9837     pic16_freeAsmop(left,NULL,ic,TRUE);
9838     pic16_freeAsmop (right,NULL,ic,TRUE);
9839     pic16_freeAsmop(result,NULL,ic,TRUE);
9840 }
9841
9842
9843 void pic16_loadFSR0(operand *op)
9844 {
9845         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9846 }
9847
9848 /*-----------------------------------------------------------------*/
9849 /* genUnpackBits - generates code for unpacking bits               */
9850 /*-----------------------------------------------------------------*/
9851 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9852 {    
9853     int shCnt ;
9854     int rlen = 0 ;
9855     sym_link *etype;
9856     int offset = 0 ;
9857
9858         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9859         etype = getSpec(operandType(result));
9860
9861         /* the following call to pic16_loadFSR0 is temporary until
9862          * optimization to handle single bit assignments is added
9863          * to the function. Until then use the old safe way! -- VR */
9864         pic16_loadFSR0( left );
9865  
9866         /* read the first byte  */
9867         switch (ptype) {
9868                 case POINTER:
9869                 case IPOINTER:
9870                 case PPOINTER:
9871                 case FPOINTER:
9872                 case GPOINTER:
9873                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9874                         break;
9875                 case CPOINTER:
9876                         pic16_emitcode("clr","a");
9877                         pic16_emitcode("movc","a","@a+dptr");
9878                         break;
9879         }
9880         
9881
9882         /* if we have bitdisplacement then it fits   */
9883         /* into this byte completely or if length is */
9884         /* less than a byte                          */
9885         if ((shCnt = SPEC_BSTR(etype)) || 
9886                 (SPEC_BLEN(etype) <= 8))  {
9887
9888                 /* shift right acc */
9889                 AccRsh(shCnt, 0);
9890
9891                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9892                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9893
9894 /* VR -- normally I would use the following, but since we use the hack,
9895  * to avoid the masking from AccRsh, why not mask it right now? */
9896
9897 /*
9898                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9899 */
9900
9901                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9902           return ;
9903         }
9904
9905
9906
9907         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9908         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9909         exit(-1);
9910
9911     /* bit field did not fit in a byte  */
9912     rlen = SPEC_BLEN(etype) - 8;
9913     pic16_aopPut(AOP(result),"a",offset++);
9914
9915     while (1)  {
9916
9917         switch (ptype) {
9918         case POINTER:
9919         case IPOINTER:
9920             pic16_emitcode("inc","%s",rname);
9921             pic16_emitcode("mov","a,@%s",rname);
9922             break;
9923             
9924         case PPOINTER:
9925             pic16_emitcode("inc","%s",rname);
9926             pic16_emitcode("movx","a,@%s",rname);
9927             break;
9928
9929         case FPOINTER:
9930             pic16_emitcode("inc","dptr");
9931             pic16_emitcode("movx","a,@dptr");
9932             break;
9933             
9934         case CPOINTER:
9935             pic16_emitcode("clr","a");
9936             pic16_emitcode("inc","dptr");
9937             pic16_emitcode("movc","a","@a+dptr");
9938             break;
9939             
9940         case GPOINTER:
9941             pic16_emitcode("inc","dptr");
9942             pic16_emitcode("lcall","__gptrget");
9943             break;
9944         }
9945
9946         rlen -= 8;            
9947         /* if we are done */
9948         if ( rlen <= 0 )
9949             break ;
9950         
9951         pic16_aopPut(AOP(result),"a",offset++);
9952                               
9953     }
9954     
9955     if (rlen) {
9956         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9957         pic16_aopPut(AOP(result),"a",offset);          
9958     }
9959     
9960     return ;
9961 }
9962
9963
9964 static void genDataPointerGet(operand *left,
9965                               operand *result,
9966                               iCode *ic)
9967 {
9968   int size, offset = 0, leoffset=0 ;
9969
9970         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9971         pic16_aopOp(result, ic, FALSE);
9972
9973         size = AOP_SIZE(result);
9974 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9975
9976
9977 #if 0
9978         /* The following tests may save a redudant movff instruction when
9979          * accessing unions */
9980          
9981         /* if they are the same */
9982         if (operandsEqu (left, result)) {
9983                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9984                 goto release;
9985         }
9986 #endif
9987
9988 #if 0
9989         /* if they are the same registers */
9990         if (pic16_sameRegs(AOP(left),AOP(result))) {
9991                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9992                 goto release;
9993         }
9994 #endif
9995
9996 #if 1
9997         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9998                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9999                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10000                 goto release;
10001         }
10002 #endif
10003
10004
10005 #if 0
10006         if ( AOP_TYPE(left) == AOP_PCODE) {
10007                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10008                                 AOP(left)->aopu.pcop->name,
10009                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10010                                 PCOR(AOP(left)->aopu.pcop)->instance:
10011                                 PCOI(AOP(left)->aopu.pcop)->offset);
10012         }
10013 #endif
10014
10015         if(AOP(left)->aopu.pcop->type == PO_DIR)
10016                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10017
10018         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10019
10020         while (size--) {
10021                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10022                 
10023                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10024                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10025                         mov2w(AOP(left), offset); // patch 8
10026                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10027                 } else {
10028                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10029                                 pic16_popGet(AOP(left), offset), //patch 8
10030                                 pic16_popGet(AOP(result), offset)));
10031                 }
10032
10033                 offset++;
10034                 leoffset++;
10035         }
10036
10037 release:
10038     pic16_freeAsmop(result,NULL,ic,TRUE);
10039 }
10040
10041
10042
10043 /*-----------------------------------------------------------------*/
10044 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10045 /*-----------------------------------------------------------------*/
10046 static void genNearPointerGet (operand *left, 
10047                                operand *result, 
10048                                iCode *ic)
10049 {
10050     asmop *aop = NULL;
10051     //regs *preg = NULL ;
10052     sym_link *rtype, *retype;
10053     sym_link *ltype = operandType(left);    
10054
10055         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10056         rtype = operandType(result);
10057         retype= getSpec(rtype);
10058     
10059         pic16_aopOp(left,ic,FALSE);
10060
10061 //      pic16_DumpOp("(left)",left);
10062 //      pic16_DumpOp("(result)",result);
10063
10064         /* if left is rematerialisable and
10065          * result is not bit variable type and
10066          * the left is pointer to data space i.e
10067          * lower 128 bytes of space */
10068         if (AOP_TYPE(left) == AOP_PCODE
10069                 && !IS_BITFIELD(retype)
10070                 && DCL_TYPE(ltype) == POINTER) {
10071
10072                 genDataPointerGet (left,result,ic);
10073                 pic16_freeAsmop(left, NULL, ic, TRUE);
10074           return ;
10075         }
10076     
10077         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10078
10079         /* if the value is already in a pointer register
10080          * then don't need anything more */
10081         if (!AOP_INPREG(AOP(left))) {
10082                 /* otherwise get a free pointer register */
10083                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10084                 
10085                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10086                 if( (AOP_TYPE(left) == AOP_PCODE) 
10087                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10088                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
10089                 {
10090                         if(!IS_BITFIELD(retype))
10091                                 pic16_loadFSR0( left );  // patch 10
10092                 } else {
10093                         // set up FSR0 with address from left
10094                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10095                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10096                 }
10097         }
10098 //       else
10099 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10100     
10101         pic16_aopOp (result,ic,FALSE);
10102     
10103       /* if bitfield then unpack the bits */
10104     if (IS_BITFIELD(retype)) 
10105         genUnpackBits (result, left, NULL, POINTER);
10106     else {
10107         /* we have can just get the values */
10108       int size = AOP_SIZE(result);
10109       int offset = 0;   
10110         
10111       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10112
10113
10114         /* fsr0 is loaded already -- VR */
10115 //      pic16_loadFSR0( left );
10116
10117 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10118 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10119       while(size--) {
10120
10121         if(size) {
10122                 pic16_emitpcode(POC_MOVFF,
10123                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10124                                 pic16_popGet(AOP(result), offset++)));
10125         } else {
10126                 pic16_emitpcode(POC_MOVFF,
10127                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10128                                 pic16_popGet(AOP(result), offset++)));
10129         }
10130       }
10131 #if 0
10132 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10133 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10134         if(size)
10135           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10136 #endif
10137 /*
10138         while (size--) {
10139             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10140
10141                 pic16_emitcode("mov","a,@%s",rname);
10142                 pic16_aopPut(AOP(result),"a",offset);
10143             } else {
10144                 sprintf(buffer,"@%s",rname);
10145                 pic16_aopPut(AOP(result),buffer,offset);
10146             }
10147             offset++ ;
10148             if (size)
10149                 pic16_emitcode("inc","%s",rname);
10150         }
10151 */
10152     }
10153
10154     /* now some housekeeping stuff */
10155     if (aop) {
10156         /* we had to allocate for this iCode */
10157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10158         pic16_freeAsmop(NULL,aop,ic,TRUE);
10159     } else { 
10160         /* we did not allocate which means left
10161            already in a pointer register, then
10162            if size > 0 && this could be used again
10163            we have to point it back to where it 
10164            belongs */
10165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10166         if (AOP_SIZE(result) > 1 &&
10167             !OP_SYMBOL(left)->remat &&
10168             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10169               ic->depth )) {
10170 //          int size = AOP_SIZE(result) - 1;
10171 //          while (size--)
10172 //              pic16_emitcode("dec","%s",rname);
10173         }
10174     }
10175
10176     /* done */
10177     pic16_freeAsmop(left,NULL,ic,TRUE);
10178     pic16_freeAsmop(result,NULL,ic,TRUE);
10179      
10180 }
10181
10182 /*-----------------------------------------------------------------*/
10183 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10184 /*-----------------------------------------------------------------*/
10185 static void genPagedPointerGet (operand *left, 
10186                                operand *result, 
10187                                iCode *ic)
10188 {
10189     asmop *aop = NULL;
10190     regs *preg = NULL ;
10191     char *rname ;
10192     sym_link *rtype, *retype;    
10193
10194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10195
10196     rtype = operandType(result);
10197     retype= getSpec(rtype);
10198     
10199     pic16_aopOp(left,ic,FALSE);
10200
10201   /* if the value is already in a pointer register
10202        then don't need anything more */
10203     if (!AOP_INPREG(AOP(left))) {
10204         /* otherwise get a free pointer register */
10205         aop = newAsmop(0);
10206         preg = getFreePtr(ic,&aop,FALSE);
10207         pic16_emitcode("mov","%s,%s",
10208                 preg->name,
10209                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10210         rname = preg->name ;
10211     } else
10212         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10213     
10214     pic16_freeAsmop(left,NULL,ic,TRUE);
10215     pic16_aopOp (result,ic,FALSE);
10216
10217     /* if bitfield then unpack the bits */
10218     if (IS_BITFIELD(retype)) 
10219         genUnpackBits (result,left,rname,PPOINTER);
10220     else {
10221         /* we have can just get the values */
10222         int size = AOP_SIZE(result);
10223         int offset = 0 ;        
10224         
10225         while (size--) {
10226             
10227             pic16_emitcode("movx","a,@%s",rname);
10228             pic16_aopPut(AOP(result),"a",offset);
10229             
10230             offset++ ;
10231             
10232             if (size)
10233                 pic16_emitcode("inc","%s",rname);
10234         }
10235     }
10236
10237     /* now some housekeeping stuff */
10238     if (aop) {
10239         /* we had to allocate for this iCode */
10240         pic16_freeAsmop(NULL,aop,ic,TRUE);
10241     } else { 
10242         /* we did not allocate which means left
10243            already in a pointer register, then
10244            if size > 0 && this could be used again
10245            we have to point it back to where it 
10246            belongs */
10247         if (AOP_SIZE(result) > 1 &&
10248             !OP_SYMBOL(left)->remat &&
10249             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10250               ic->depth )) {
10251             int size = AOP_SIZE(result) - 1;
10252             while (size--)
10253                 pic16_emitcode("dec","%s",rname);
10254         }
10255     }
10256
10257     /* done */
10258     pic16_freeAsmop(result,NULL,ic,TRUE);
10259     
10260         
10261 }
10262
10263 /*-----------------------------------------------------------------*/
10264 /* genFarPointerGet - gget value from far space                    */
10265 /*-----------------------------------------------------------------*/
10266 static void genFarPointerGet (operand *left,
10267                               operand *result, iCode *ic)
10268 {
10269     int size, offset ;
10270     sym_link *retype = getSpec(operandType(result));
10271
10272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10273
10274     pic16_aopOp(left,ic,FALSE);
10275
10276     /* if the operand is already in dptr 
10277     then we do nothing else we move the value to dptr */
10278     if (AOP_TYPE(left) != AOP_STR) {
10279         /* if this is remateriazable */
10280         if (AOP_TYPE(left) == AOP_IMMD)
10281             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10282         else { /* we need to get it byte by byte */
10283             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10284             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10285             if (options.model == MODEL_FLAT24)
10286             {
10287                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10288             }
10289         }
10290     }
10291     /* so dptr know contains the address */
10292     pic16_freeAsmop(left,NULL,ic,TRUE);
10293     pic16_aopOp(result,ic,FALSE);
10294
10295     /* if bit then unpack */
10296     if (IS_BITFIELD(retype)) 
10297         genUnpackBits(result,left,"dptr",FPOINTER);
10298     else {
10299         size = AOP_SIZE(result);
10300         offset = 0 ;
10301
10302         while (size--) {
10303             pic16_emitcode("movx","a,@dptr");
10304             pic16_aopPut(AOP(result),"a",offset++);
10305             if (size)
10306                 pic16_emitcode("inc","dptr");
10307         }
10308     }
10309
10310     pic16_freeAsmop(result,NULL,ic,TRUE);
10311 }
10312 #if 0
10313 /*-----------------------------------------------------------------*/
10314 /* genCodePointerGet - get value from code space                  */
10315 /*-----------------------------------------------------------------*/
10316 static void genCodePointerGet (operand *left,
10317                                 operand *result, iCode *ic)
10318 {
10319     int size, offset ;
10320     sym_link *retype = getSpec(operandType(result));
10321
10322     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10323
10324     pic16_aopOp(left,ic,FALSE);
10325
10326     /* if the operand is already in dptr 
10327     then we do nothing else we move the value to dptr */
10328     if (AOP_TYPE(left) != AOP_STR) {
10329         /* if this is remateriazable */
10330         if (AOP_TYPE(left) == AOP_IMMD)
10331             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10332         else { /* we need to get it byte by byte */
10333             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10334             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10335             if (options.model == MODEL_FLAT24)
10336             {
10337                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10338             }
10339         }
10340     }
10341     /* so dptr know contains the address */
10342     pic16_freeAsmop(left,NULL,ic,TRUE);
10343     pic16_aopOp(result,ic,FALSE);
10344
10345     /* if bit then unpack */
10346     if (IS_BITFIELD(retype)) 
10347         genUnpackBits(result,left,"dptr",CPOINTER);
10348     else {
10349         size = AOP_SIZE(result);
10350         offset = 0 ;
10351
10352         while (size--) {
10353             pic16_emitcode("clr","a");
10354             pic16_emitcode("movc","a,@a+dptr");
10355             pic16_aopPut(AOP(result),"a",offset++);
10356             if (size)
10357                 pic16_emitcode("inc","dptr");
10358         }
10359     }
10360
10361     pic16_freeAsmop(result,NULL,ic,TRUE);
10362 }
10363 #endif
10364 #if 0
10365 /*-----------------------------------------------------------------*/
10366 /* genGenPointerGet - gget value from generic pointer space        */
10367 /*-----------------------------------------------------------------*/
10368 static void genGenPointerGet (operand *left,
10369                               operand *result, iCode *ic)
10370 {
10371   int size, offset, lit;
10372   sym_link *retype = getSpec(operandType(result));
10373
10374         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10375         pic16_aopOp(left,ic,FALSE);
10376         pic16_aopOp(result,ic,FALSE);
10377         size = AOP_SIZE(result);
10378
10379         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10380
10381         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10382
10383                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10384                 // load FSR0 from immediate
10385                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10386
10387 //              pic16_loadFSR0( left );
10388
10389                 offset = 0;
10390                 while(size--) {
10391                         if(size) {
10392                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10393                         } else {
10394                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10395                         }
10396                         offset++;
10397                 }
10398                 goto release;
10399
10400         }
10401         else { /* we need to get it byte by byte */
10402                 // set up FSR0 with address from left
10403                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10404                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10405
10406                 offset = 0 ;
10407
10408                 while(size--) {
10409                         if(size) {
10410                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10411                         } else {
10412                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10413                         }
10414                         offset++;
10415                 }
10416                 goto release;
10417         }
10418
10419   /* if bit then unpack */
10420         if (IS_BITFIELD(retype)) 
10421                 genUnpackBits(result,left,"BAD",GPOINTER);
10422
10423         release:
10424         pic16_freeAsmop(left,NULL,ic,TRUE);
10425         pic16_freeAsmop(result,NULL,ic,TRUE);
10426
10427 }
10428 #endif
10429
10430 extern set *externs;
10431
10432 /*-----------------------------------------------------------------*/
10433 /* genGenPointerGet - gget value from generic pointer space        */
10434 /*-----------------------------------------------------------------*/
10435 static void genGenPointerGet (operand *left,
10436                               operand *result, iCode *ic)
10437 {
10438   int size, offset, lit;
10439   sym_link *retype = getSpec(operandType(result));
10440   char fgptrget[32];
10441
10442     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10443     pic16_aopOp(left,ic,FALSE);
10444     pic16_aopOp(result,ic,FALSE);
10445     size = AOP_SIZE(result);
10446
10447     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10448
10449     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10450
10451       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10452       // load FSR0 from immediate
10453       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10454
10455       werror(W_POSSBUG2, __FILE__, __LINE__);
10456
10457       offset = 0;
10458       while(size--) {
10459         if(size) {
10460           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10461         } else {
10462           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10463         }
10464         offset++;
10465       }
10466
10467       goto release;
10468
10469     } else { /* we need to get it byte by byte */
10470
10471       /* set up WREG:PRODL:FSR0L with address from left */
10472       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10473       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10474       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10475       
10476       switch( size ) {
10477         case 1: strcpy(fgptrget, "__gptrget1"); break;
10478         case 2: strcpy(fgptrget, "__gptrget2"); break;
10479         case 3: strcpy(fgptrget, "__gptrget3"); break;
10480         case 4: strcpy(fgptrget, "__gptrget4"); break;
10481         default:
10482           werror(W_POSSBUG2, __FILE__, __LINE__);
10483           abort();
10484       }
10485       
10486       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10487       
10488       assignResultValue(result, 1);
10489       
10490       {
10491         symbol *sym;
10492
10493           sym = newSymbol( fgptrget, 0 );
10494           strcpy(sym->rname, fgptrget);
10495           checkAddSym(&externs, sym);
10496
10497 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10498       }
10499               
10500       goto release;
10501     }
10502
10503   /* if bit then unpack */
10504     if (IS_BITFIELD(retype)) 
10505       genUnpackBits(result,left,"BAD",GPOINTER);
10506
10507 release:
10508   pic16_freeAsmop(left,NULL,ic,TRUE);
10509   pic16_freeAsmop(result,NULL,ic,TRUE);
10510 }
10511
10512 /*-----------------------------------------------------------------*/
10513 /* genConstPointerGet - get value from const generic pointer space */
10514 /*-----------------------------------------------------------------*/
10515 static void genConstPointerGet (operand *left,
10516                                 operand *result, iCode *ic)
10517 {
10518   //sym_link *retype = getSpec(operandType(result));
10519   // symbol *albl = newiTempLabel(NULL);        // patch 15
10520   // symbol *blbl = newiTempLabel(NULL);        //
10521   // PIC_OPCODE poc;                            // patch 15
10522   int size;
10523   int offset = 0;
10524
10525   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10526   pic16_aopOp(left,ic,FALSE);
10527   pic16_aopOp(result,ic,TRUE);
10528   size = AOP_SIZE(result);
10529
10530   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10531
10532   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10533 #if 0                                                                   // patch 15
10534   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10535   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10536   pic16_emitpLabel(albl->key);
10537
10538   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10539   
10540   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10541   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10542   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10543   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10544   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10545
10546   pic16_emitpLabel(blbl->key);
10547
10548   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10549 #endif                                                                  // patch 15
10550
10551
10552   // set up table pointer
10553   if( (AOP_TYPE(left) == AOP_PCODE) 
10554       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10555           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
10556     {
10557       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10558       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10559       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10560       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10561       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10562       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10563     }
10564   else
10565     {
10566       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10567       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10568       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10569     }
10570
10571
10572   while(size--)
10573     {
10574       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10575       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10576       offset++;
10577     }
10578     
10579   pic16_freeAsmop(left,NULL,ic,TRUE);
10580   pic16_freeAsmop(result,NULL,ic,TRUE);
10581
10582 }
10583
10584
10585 /*-----------------------------------------------------------------*/
10586 /* genPointerGet - generate code for pointer get                   */
10587 /*-----------------------------------------------------------------*/
10588 static void genPointerGet (iCode *ic)
10589 {
10590     operand *left, *result ;
10591     sym_link *type, *etype;
10592     int p_type;
10593
10594     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10595
10596     left = IC_LEFT(ic);
10597     result = IC_RESULT(ic) ;
10598
10599     /* depending on the type of pointer we need to
10600     move it to the correct pointer register */
10601     type = operandType(left);
10602     etype = getSpec(type);
10603
10604 #if 0
10605     if (IS_PTR_CONST(type))
10606 #else
10607     if (IS_CODEPTR(type))
10608 #endif
10609       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10610
10611     /* if left is of type of pointer then it is simple */
10612     if (IS_PTR(type) && !IS_FUNC(type->next)) 
10613         p_type = DCL_TYPE(type);
10614     else {
10615         /* we have to go by the storage class */
10616         p_type = PTR_TYPE(SPEC_OCLS(etype));
10617
10618         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10619
10620         if (SPEC_OCLS(etype)->codesp ) {
10621           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10622           //p_type = CPOINTER ; 
10623         }
10624         else
10625             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10626               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10627                /*p_type = FPOINTER ;*/ 
10628             else
10629                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10630                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10631 /*                  p_type = PPOINTER; */
10632                 else
10633                     if (SPEC_OCLS(etype) == idata )
10634                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10635 /*                      p_type = IPOINTER; */
10636                     else
10637                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10638 /*                      p_type = POINTER ; */
10639     }
10640
10641     /* now that we have the pointer type we assign
10642     the pointer values */
10643     switch (p_type) {
10644
10645     case POINTER:       
10646     case IPOINTER:
10647         genNearPointerGet (left,result,ic);
10648         break;
10649
10650     case PPOINTER:
10651         genPagedPointerGet(left,result,ic);
10652         break;
10653
10654     case FPOINTER:
10655         genFarPointerGet (left,result,ic);
10656         break;
10657
10658     case CPOINTER:
10659         genConstPointerGet (left,result,ic);
10660         //pic16_emitcodePointerGet (left,result,ic);
10661         break;
10662
10663     case GPOINTER:
10664 #if 0
10665       if (IS_PTR_CONST(type))
10666         genConstPointerGet (left,result,ic);
10667       else
10668 #endif
10669         genGenPointerGet (left,result,ic);
10670       break;
10671
10672     default:
10673       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10674               "genPointerGet: illegal pointer type");
10675     
10676     }
10677
10678 }
10679
10680 /*-----------------------------------------------------------------*/
10681 /* genPackBits - generates code for packed bit storage             */
10682 /*-----------------------------------------------------------------*/
10683 static void genPackBits (sym_link    *etype , operand *result,
10684                          operand *right ,
10685                          char *rname, int p_type)
10686 {
10687   int shCnt = 0 ;
10688   int offset = 0  ;
10689   int rLen = 0 ;
10690   int blen, bstr ;   
10691   char *l ;
10692
10693         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10694         blen = SPEC_BLEN(etype);
10695         bstr = SPEC_BSTR(etype);
10696
10697         if(AOP_TYPE(right) == AOP_LIT) {
10698                 if((blen == 1) && (bstr < 8)) {
10699                   unsigned long lit;
10700                         /* it is a single bit, so use the appropriate bit instructions */
10701
10702                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10703
10704                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10705 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10706                         if((p_type == POINTER) && (result)) {
10707                                 /* workaround to reduce the extra lfsr instruction */
10708                                 if(lit) {
10709                                         pic16_emitpcode(POC_BSF,
10710                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10711                                 } else {
10712                                         pic16_emitpcode(POC_BCF,
10713                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10714                                 }
10715                         } else {
10716
10717                                 if(lit) {
10718                                         pic16_emitpcode(POC_BSF,
10719                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10720                                 } else {
10721                                         pic16_emitpcode(POC_BCF,
10722                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10723                                 }
10724                         }
10725         
10726                   return;
10727                 }
10728
10729                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10730                 offset++;
10731         } else
10732                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10733
10734         /* if the bit lenth is less than or    */
10735         /* it exactly fits a byte then         */
10736         if((shCnt=SPEC_BSTR(etype))
10737                 || SPEC_BLEN(etype) <= 8 )  {
10738
10739                 /* shift left acc */
10740                 AccLsh(shCnt);
10741
10742                 /* using PRODL as a temporary register here */
10743                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10744
10745                 switch (p_type) {
10746                         case FPOINTER:
10747                         case POINTER:
10748                         case GPOINTER:
10749                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10750 //                              pic16_emitcode ("mov","b,a");
10751 //                              pic16_emitcode("mov","a,@%s",rname);
10752                                 break;
10753                 }
10754 #if 1
10755                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10756                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10757                                         (unsigned char)(0xff >> (8-bstr))) ));
10758                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10759                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10760 #endif
10761
10762           return;
10763         }
10764
10765
10766         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10767         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10768         exit(-1);
10769
10770
10771     /* if we r done */
10772     if ( SPEC_BLEN(etype) <= 8 )
10773         return ;
10774
10775     pic16_emitcode("inc","%s",rname);
10776     rLen = SPEC_BLEN(etype) ;     
10777
10778
10779
10780     /* now generate for lengths greater than one byte */
10781     while (1) {
10782
10783         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10784
10785         rLen -= 8 ;
10786         if (rLen <= 0 )
10787             break ;
10788
10789         switch (p_type) {
10790             case POINTER:
10791                 if (*l == '@') {
10792                     MOVA(l);
10793                     pic16_emitcode("mov","@%s,a",rname);
10794                 } else
10795                     pic16_emitcode("mov","@%s,%s",rname,l);
10796                 break;
10797
10798             case FPOINTER:
10799                 MOVA(l);
10800                 pic16_emitcode("movx","@dptr,a");
10801                 break;
10802
10803             case GPOINTER:
10804                 MOVA(l);
10805                 DEBUGpic16_emitcode(";lcall","__gptrput");
10806                 break;  
10807         }   
10808         pic16_emitcode ("inc","%s",rname);
10809     }
10810
10811     MOVA(l);
10812
10813     /* last last was not complete */
10814     if (rLen)   {
10815         /* save the byte & read byte */
10816         switch (p_type) {
10817             case POINTER:
10818                 pic16_emitcode ("mov","b,a");
10819                 pic16_emitcode("mov","a,@%s",rname);
10820                 break;
10821
10822             case FPOINTER:
10823                 pic16_emitcode ("mov","b,a");
10824                 pic16_emitcode("movx","a,@dptr");
10825                 break;
10826
10827             case GPOINTER:
10828                 pic16_emitcode ("push","b");
10829                 pic16_emitcode ("push","acc");
10830                 pic16_emitcode ("lcall","__gptrget");
10831                 pic16_emitcode ("pop","b");
10832                 break;
10833         }
10834
10835         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10836         pic16_emitcode ("orl","a,b");
10837     }
10838
10839     if (p_type == GPOINTER)
10840         pic16_emitcode("pop","b");
10841
10842     switch (p_type) {
10843
10844     case POINTER:
10845         pic16_emitcode("mov","@%s,a",rname);
10846         break;
10847         
10848     case FPOINTER:
10849         pic16_emitcode("movx","@dptr,a");
10850         break;
10851         
10852     case GPOINTER:
10853         DEBUGpic16_emitcode(";lcall","__gptrput");
10854         break;                  
10855     }
10856 }
10857 /*-----------------------------------------------------------------*/
10858 /* genDataPointerSet - remat pointer to data space                 */
10859 /*-----------------------------------------------------------------*/
10860 static void genDataPointerSet(operand *right,
10861                               operand *result,
10862                               iCode *ic)
10863 {
10864     int size, offset = 0, resoffset=0 ;
10865
10866     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10867     pic16_aopOp(right,ic,FALSE);
10868
10869     size = AOP_SIZE(right);
10870
10871 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10872
10873 #if 0
10874     if ( AOP_TYPE(result) == AOP_PCODE) {
10875       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10876               AOP(result)->aopu.pcop->name,
10877                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10878               PCOR(AOP(result)->aopu.pcop)->instance:
10879               PCOI(AOP(result)->aopu.pcop)->offset);
10880     }
10881 #endif
10882
10883         if(AOP(result)->aopu.pcop->type == PO_DIR)
10884                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10885
10886         while (size--) {
10887                 if (AOP_TYPE(right) == AOP_LIT) {
10888                   unsigned int lit;
10889
10890                     if(!IS_FLOAT(operandType( right )))
10891                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10892                     else {
10893                       union {
10894                         unsigned long lit_int;
10895                         float lit_float;
10896                       } info;
10897         
10898                         /* take care if literal is a float */
10899                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10900                         lit = info.lit_int;
10901                     }
10902
10903                     lit = lit >> (8*offset);
10904                     if(lit&0xff) {
10905                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10906                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10907                     } else {
10908                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10909                     }
10910                 } else {
10911                   mov2w(AOP(right), offset);
10912                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10913                 }
10914                 offset++;
10915                 resoffset++;
10916         }
10917
10918     pic16_freeAsmop(right,NULL,ic,TRUE);
10919 }
10920
10921
10922
10923 /*-----------------------------------------------------------------*/
10924 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10925 /*-----------------------------------------------------------------*/
10926 static void genNearPointerSet (operand *right,
10927                                operand *result, 
10928                                iCode *ic)
10929 {
10930   asmop *aop = NULL;
10931   char *l;
10932   sym_link *retype;
10933   sym_link *ptype = operandType(result);
10934   sym_link *resetype;
10935     
10936         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10937         retype= getSpec(operandType(right));
10938         resetype = getSpec(operandType(result));
10939   
10940         pic16_aopOp(result,ic,FALSE);
10941     
10942         /* if the result is rematerializable &
10943          * in data space & not a bit variable */
10944         
10945         /* and result is not a bit variable */
10946         if (AOP_TYPE(result) == AOP_PCODE
10947 //              && AOP_TYPE(result) == AOP_IMMD
10948                 && DCL_TYPE(ptype) == POINTER
10949                 && !IS_BITFIELD(retype)
10950                 && !IS_BITFIELD(resetype)) {
10951
10952                 genDataPointerSet (right,result,ic);
10953                 pic16_freeAsmop(result,NULL,ic,TRUE);
10954           return;
10955         }
10956
10957         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10958         pic16_aopOp(right,ic,FALSE);
10959         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10960
10961         /* if the value is already in a pointer register
10962          * then don't need anything more */
10963         if (!AOP_INPREG(AOP(result))) {
10964                 /* otherwise get a free pointer register */
10965                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10966
10967                 if( (AOP_TYPE(result) == AOP_PCODE) 
10968                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10969                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10970                 {
10971                   if(!IS_BITFIELD(resetype))
10972                         pic16_loadFSR0( result );  // patch 10
10973                 } else {
10974                         // set up FSR0 with address of result
10975                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10976                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10977                 }
10978
10979         }
10980 //      else
10981 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10982
10983         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10984
10985         /* if bitfield then unpack the bits */
10986         if (IS_BITFIELD(resetype)) {
10987                 genPackBits (resetype, result, right, NULL, POINTER);
10988         } else {
10989                 /* we have can just get the values */
10990           int size = AOP_SIZE(right);
10991           int offset = 0 ;    
10992
10993                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10994                 while (size--) {
10995                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10996                         if (*l == '@' ) {
10997                                 //MOVA(l);
10998                                 //pic16_emitcode("mov","@%s,a",rname);
10999                                 pic16_emitcode("movf","indf0,w ;1");
11000                         } else {
11001
11002                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11003                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11004                                         if (size) {                                                                     // 
11005                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11006                                         } else {                                                                        // 
11007                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11008                                         }                                                                               // 
11009                                 } else { // no literal                                                                  // 
11010                                         if(size) {                                                                      // 
11011                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11012                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11013                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11014                                         } else {                                                                        // 
11015                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11016                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11017                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11018                                         }                                                                               //
11019                                 }                                                                                       // patch 10
11020                         }
11021                         offset++;
11022                 }
11023         }
11024
11025         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11026         /* now some housekeeping stuff */
11027         if (aop) {
11028                 /* we had to allocate for this iCode */
11029                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11030         } else { 
11031                 /* we did not allocate which means left
11032                  * already in a pointer register, then
11033                  * if size > 0 && this could be used again
11034                  * we have to point it back to where it 
11035                  * belongs */
11036                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11037                 if (AOP_SIZE(right) > 1
11038                         && !OP_SYMBOL(result)->remat
11039                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11040                                 || ic->depth )) {
11041
11042                   int size = AOP_SIZE(right) - 1;
11043
11044                         while (size--)
11045                                 pic16_emitcode("decf","fsr0,f");
11046                         //pic16_emitcode("dec","%s",rname);
11047                 }
11048         }
11049
11050         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11051         /* done */
11052 //release:
11053         pic16_freeAsmop(right,NULL,ic,TRUE);
11054         pic16_freeAsmop(result,NULL,ic,TRUE);
11055 }
11056
11057 /*-----------------------------------------------------------------*/
11058 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11059 /*-----------------------------------------------------------------*/
11060 static void genPagedPointerSet (operand *right,
11061                                operand *result, 
11062                                iCode *ic)
11063 {
11064     asmop *aop = NULL;
11065     regs *preg = NULL ;
11066     char *rname , *l;
11067     sym_link *retype;
11068        
11069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11070
11071     retype= getSpec(operandType(right));
11072     
11073     pic16_aopOp(result,ic,FALSE);
11074     
11075     /* if the value is already in a pointer register
11076        then don't need anything more */
11077     if (!AOP_INPREG(AOP(result))) {
11078         /* otherwise get a free pointer register */
11079         aop = newAsmop(0);
11080         preg = getFreePtr(ic,&aop,FALSE);
11081         pic16_emitcode("mov","%s,%s",
11082                 preg->name,
11083                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11084         rname = preg->name ;
11085     } else
11086         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11087     
11088     pic16_freeAsmop(result,NULL,ic,TRUE);
11089     pic16_aopOp (right,ic,FALSE);
11090
11091     /* if bitfield then unpack the bits */
11092     if (IS_BITFIELD(retype)) 
11093         genPackBits (retype,result,right,rname,PPOINTER);
11094     else {
11095         /* we have can just get the values */
11096         int size = AOP_SIZE(right);
11097         int offset = 0 ;        
11098         
11099         while (size--) {
11100             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11101             
11102             MOVA(l);
11103             pic16_emitcode("movx","@%s,a",rname);
11104
11105             if (size)
11106                 pic16_emitcode("inc","%s",rname);
11107
11108             offset++;
11109         }
11110     }
11111     
11112     /* now some housekeeping stuff */
11113     if (aop) {
11114         /* we had to allocate for this iCode */
11115         pic16_freeAsmop(NULL,aop,ic,TRUE);
11116     } else { 
11117         /* we did not allocate which means left
11118            already in a pointer register, then
11119            if size > 0 && this could be used again
11120            we have to point it back to where it 
11121            belongs */
11122         if (AOP_SIZE(right) > 1 &&
11123             !OP_SYMBOL(result)->remat &&
11124             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11125               ic->depth )) {
11126             int size = AOP_SIZE(right) - 1;
11127             while (size--)
11128                 pic16_emitcode("dec","%s",rname);
11129         }
11130     }
11131
11132     /* done */
11133     pic16_freeAsmop(right,NULL,ic,TRUE);
11134     
11135         
11136 }
11137
11138 /*-----------------------------------------------------------------*/
11139 /* genFarPointerSet - set value from far space                     */
11140 /*-----------------------------------------------------------------*/
11141 static void genFarPointerSet (operand *right,
11142                               operand *result, iCode *ic)
11143 {
11144     int size, offset ;
11145     sym_link *retype = getSpec(operandType(right));
11146
11147     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11148     pic16_aopOp(result,ic,FALSE);
11149
11150     /* if the operand is already in dptr 
11151     then we do nothing else we move the value to dptr */
11152     if (AOP_TYPE(result) != AOP_STR) {
11153         /* if this is remateriazable */
11154         if (AOP_TYPE(result) == AOP_IMMD)
11155             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11156         else { /* we need to get it byte by byte */
11157             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11158             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11159             if (options.model == MODEL_FLAT24)
11160             {
11161                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11162             }
11163         }
11164     }
11165     /* so dptr know contains the address */
11166     pic16_freeAsmop(result,NULL,ic,TRUE);
11167     pic16_aopOp(right,ic,FALSE);
11168
11169     /* if bit then unpack */
11170     if (IS_BITFIELD(retype)) 
11171         genPackBits(retype,result,right,"dptr",FPOINTER);
11172     else {
11173         size = AOP_SIZE(right);
11174         offset = 0 ;
11175
11176         while (size--) {
11177             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11178             MOVA(l);
11179             pic16_emitcode("movx","@dptr,a");
11180             if (size)
11181                 pic16_emitcode("inc","dptr");
11182         }
11183     }
11184
11185     pic16_freeAsmop(right,NULL,ic,TRUE);
11186 }
11187
11188 /*-----------------------------------------------------------------*/
11189 /* genGenPointerSet - set value from generic pointer space         */
11190 /*-----------------------------------------------------------------*/
11191 #if 0
11192 static void genGenPointerSet (operand *right,
11193                               operand *result, iCode *ic)
11194 {
11195         int i, size, offset, lit;
11196         sym_link *retype = getSpec(operandType(right));
11197
11198         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11199
11200         pic16_aopOp(result,ic,FALSE);
11201         pic16_aopOp(right,ic,FALSE);
11202         size = AOP_SIZE(right);
11203         offset = 0;
11204
11205         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11206
11207         /* if the operand is already in dptr 
11208                 then we do nothing else we move the value to dptr */
11209         if (AOP_TYPE(result) != AOP_STR) {
11210                 /* if this is remateriazable */
11211                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11212                 // WARNING: anythig until "else" is untested!
11213                 if (AOP_TYPE(result) == AOP_IMMD) {
11214                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11215                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11216                         // load FSR0 from immediate
11217                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11218                         offset = 0;
11219                         while(size--) {
11220                                 if(size) {
11221                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11222                                 } else {
11223                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11224                                 }
11225                                 offset++;
11226                         }
11227                         goto release;
11228                 }
11229                 else { /* we need to get it byte by byte */
11230                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11231                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11232
11233                         // set up FSR0 with address of result
11234                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11235                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11236
11237                         /* hack hack! see if this the FSR. If so don't load W */
11238                         if(AOP_TYPE(right) != AOP_ACC) {
11239
11240                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11241
11242                                 if(AOP_TYPE(right) == AOP_LIT)
11243                                 {
11244                                         // copy literal
11245                                         // note: pic16_popGet handles sign extension
11246                                         for(i=0;i<size;i++) {
11247                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11248                                                 if(i < size-1)
11249                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11250                                                 else
11251                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11252                                         }
11253                                 } else {
11254                                         // copy regs
11255
11256                                         for(i=0;i<size;i++) {
11257                                                 if(i < size-1)
11258                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11259                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11260                                                 else
11261                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11262                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11263                                         }
11264                                 }
11265                                 goto release;
11266                         } 
11267                         // right = ACC
11268                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11269                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11270                         goto release;
11271         } // if (AOP_TYPE(result) != AOP_IMMD)
11272
11273         } // if (AOP_TYPE(result) != AOP_STR)
11274         /* so dptr know contains the address */
11275
11276
11277         /* if bit then unpack */
11278         if (IS_BITFIELD(retype)) 
11279                 genPackBits(retype,result,right,"dptr",GPOINTER);
11280         else {
11281                 size = AOP_SIZE(right);
11282                 offset = 0 ;
11283
11284                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11285
11286                 // set up FSR0 with address of result
11287                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11288                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11289         
11290                 while (size--) {
11291                         if (AOP_TYPE(right) == AOP_LIT) {
11292                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11293                                 if (size) {
11294                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11295                                 } else {
11296                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11297                                 }
11298                         } else { // no literal
11299                                 if(size) {
11300                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11301                                 } else {
11302                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11303                                 }
11304                         }
11305                         offset++;
11306                 }
11307         }
11308
11309         release:
11310         pic16_freeAsmop(right,NULL,ic,TRUE);
11311         pic16_freeAsmop(result,NULL,ic,TRUE);
11312 }
11313 #endif
11314
11315 static void genGenPointerSet (operand *right,
11316                               operand *result, iCode *ic)
11317 {
11318   int size;
11319   sym_link *retype = getSpec(operandType(right));
11320   char fgptrput[32];
11321
11322     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11323
11324     pic16_aopOp(result,ic,FALSE);
11325     pic16_aopOp(right,ic,FALSE);
11326     size = AOP_SIZE(right);
11327
11328     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11329
11330
11331     /* if bit then unpack */
11332     if (IS_BITFIELD(retype)) {
11333 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11334       genPackBits(retype,result,right,"dptr",GPOINTER);
11335       goto release;
11336     }
11337
11338     size = AOP_SIZE(right);
11339
11340     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11341
11342
11343
11344     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11345
11346     /* value of right+0 is placed on stack, which will be retrieved
11347      * by the support function this restoring the stack. The important
11348      * thing is that there is no need to manually restore stack pointer
11349      * here */
11350     mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11351     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11352     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11353     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11354     
11355     /* load address to write to in WREG:FSR0H:FSR0L */
11356     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11357                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11358     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11359                                 pic16_popCopyReg(&pic16_pc_prodl)));
11360     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11361     
11362
11363     /* put code here */
11364     switch (size) {
11365       case 1: strcpy(fgptrput, "__gptrput1"); break;
11366       case 2: strcpy(fgptrput, "__gptrput2"); break;
11367       case 3: strcpy(fgptrput, "__gptrput3"); break;
11368       case 4: strcpy(fgptrput, "__gptrput4"); break;
11369       default:
11370         werror(W_POSSBUG2, __FILE__, __LINE__);
11371         abort();
11372     }
11373     
11374     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11375     
11376     {
11377       symbol *sym;
11378                   
11379         sym = newSymbol( fgptrput, 0 );
11380         strcpy(sym->rname, fgptrput);
11381         checkAddSym(&externs, sym);
11382     }
11383
11384 release:
11385     pic16_freeAsmop(right,NULL,ic,TRUE);
11386     pic16_freeAsmop(result,NULL,ic,TRUE);
11387 }
11388
11389 /*-----------------------------------------------------------------*/
11390 /* genPointerSet - stores the value into a pointer location        */
11391 /*-----------------------------------------------------------------*/
11392 static void genPointerSet (iCode *ic)
11393 {    
11394     operand *right, *result ;
11395     sym_link *type, *etype;
11396     int p_type;
11397
11398     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11399
11400     right = IC_RIGHT(ic);
11401     result = IC_RESULT(ic) ;
11402
11403     /* depending on the type of pointer we need to
11404     move it to the correct pointer register */
11405     type = operandType(result);
11406     etype = getSpec(type);
11407     /* if left is of type of pointer then it is simple */
11408     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11409         p_type = DCL_TYPE(type);
11410     }
11411     else {
11412         /* we have to go by the storage class */
11413         p_type = PTR_TYPE(SPEC_OCLS(etype));
11414
11415 /*      if (SPEC_OCLS(etype)->codesp ) { */
11416 /*          p_type = CPOINTER ;  */
11417 /*      } */
11418 /*      else */
11419 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11420 /*              p_type = FPOINTER ; */
11421 /*          else */
11422 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11423 /*                  p_type = PPOINTER ; */
11424 /*              else */
11425 /*                  if (SPEC_OCLS(etype) == idata ) */
11426 /*                      p_type = IPOINTER ; */
11427 /*                  else */
11428 /*                      p_type = POINTER ; */
11429     }
11430
11431     /* now that we have the pointer type we assign
11432     the pointer values */
11433     switch (p_type) {
11434
11435     case POINTER:
11436     case IPOINTER:
11437         genNearPointerSet (right,result,ic);
11438         break;
11439
11440     case PPOINTER:
11441         genPagedPointerSet (right,result,ic);
11442         break;
11443
11444     case FPOINTER:
11445         genFarPointerSet (right,result,ic);
11446         break;
11447
11448     case GPOINTER:
11449         genGenPointerSet (right,result,ic);
11450         break;
11451
11452     default:
11453       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11454               "genPointerSet: illegal pointer type");
11455     }
11456 }
11457
11458 /*-----------------------------------------------------------------*/
11459 /* genIfx - generate code for Ifx statement                        */
11460 /*-----------------------------------------------------------------*/
11461 static void genIfx (iCode *ic, iCode *popIc)
11462 {
11463   operand *cond = IC_COND(ic);
11464   int isbit =0;
11465
11466   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11467
11468   pic16_aopOp(cond,ic,FALSE);
11469
11470   /* get the value into acc */
11471   if (AOP_TYPE(cond) != AOP_CRY)
11472     pic16_toBoolean(cond);
11473   else
11474     isbit = 1;
11475   /* the result is now in the accumulator */
11476   pic16_freeAsmop(cond,NULL,ic,TRUE);
11477
11478   /* if there was something to be popped then do it */
11479   if (popIc)
11480     genIpop(popIc);
11481
11482   /* if the condition is  a bit variable */
11483   if (isbit && IS_ITEMP(cond) && 
11484       SPIL_LOC(cond)) {
11485     genIfxJump(ic,SPIL_LOC(cond)->rname);
11486     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11487   }
11488   else {
11489     if (isbit && !IS_ITEMP(cond))
11490       genIfxJump(ic,OP_SYMBOL(cond)->rname);
11491     else
11492       genIfxJump(ic,"a");
11493   }
11494   ic->generated = 1;
11495
11496 }
11497
11498 /*-----------------------------------------------------------------*/
11499 /* genAddrOf - generates code for address of                       */
11500 /*-----------------------------------------------------------------*/
11501 static void genAddrOf (iCode *ic)
11502 {
11503   operand *result, *left;
11504   int size;
11505   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
11506   pCodeOp *pcop0, *pcop1, *pcop2;
11507
11508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11509
11510     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
11511
11512     sym = OP_SYMBOL( IC_LEFT(ic) );
11513     
11514     if(sym->onStack) {
11515       /* get address of symbol on stack */
11516       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
11517 #if 0
11518       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
11519                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
11520 #endif
11521
11522       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11523                       pic16_popCopyReg(&pic16_pc_fsr2l),
11524                       pic16_popGet(AOP(result), 0)));
11525       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11526                       pic16_popCopyReg(&pic16_pc_fsr2h),
11527                       pic16_popGet(AOP(result), 1)));
11528       
11529       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
11530       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
11531       emitSKPNC;
11532       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
11533
11534       goto release;
11535     }
11536         
11537 //      if(pic16_debug_verbose) {
11538 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
11539 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
11540 //      }
11541         
11542     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
11543     size = AOP_SIZE(IC_RESULT(ic));
11544
11545
11546     /* Assume that what we want the address of is in data space
11547      * since there is no stack on the PIC, yet! -- VR */
11548   
11549     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11550     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11551     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11552         
11553     if (size == 3) {
11554       pic16_emitpcode(POC_MOVLW, pcop0);
11555       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11556       pic16_emitpcode(POC_MOVLW, pcop1);
11557       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11558       pic16_emitpcode(POC_MOVLW, pcop2);
11559       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11560     } else
11561     if (size == 2) {
11562       pic16_emitpcode(POC_MOVLW, pcop0);
11563       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11564       pic16_emitpcode(POC_MOVLW, pcop1);
11565     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11566     } else {
11567       pic16_emitpcode(POC_MOVLW, pcop0);
11568       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11569     }
11570
11571     pic16_freeAsmop(left, NULL, ic, FALSE);
11572 release:
11573     pic16_freeAsmop(result,NULL,ic,TRUE);
11574 }
11575
11576
11577 #if 0
11578 /*-----------------------------------------------------------------*/
11579 /* genFarFarAssign - assignment when both are in far space         */
11580 /*-----------------------------------------------------------------*/
11581 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
11582 {
11583     int size = AOP_SIZE(right);
11584     int offset = 0;
11585     char *l ;
11586     /* first push the right side on to the stack */
11587     while (size--) {
11588         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11589         MOVA(l);
11590         pic16_emitcode ("push","acc");
11591     }
11592     
11593     pic16_freeAsmop(right,NULL,ic,FALSE);
11594     /* now assign DPTR to result */
11595     pic16_aopOp(result,ic,FALSE);
11596     size = AOP_SIZE(result);
11597     while (size--) {
11598         pic16_emitcode ("pop","acc");
11599         pic16_aopPut(AOP(result),"a",--offset);
11600     }
11601     pic16_freeAsmop(result,NULL,ic,FALSE);
11602         
11603 }
11604 #endif
11605
11606 /*-----------------------------------------------------------------*/
11607 /* genAssign - generate code for assignment                        */
11608 /*-----------------------------------------------------------------*/
11609 static void genAssign (iCode *ic)
11610 {
11611   operand *result, *right;
11612   int size, offset,know_W;
11613   unsigned long lit = 0L;
11614
11615   result = IC_RESULT(ic);
11616   right  = IC_RIGHT(ic) ;
11617
11618   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11619   
11620   /* if they are the same */
11621   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11622     return ;
11623
11624   /* reversed order operands are aopOp'ed so that result operand
11625    * is effective in case right is a stack symbol. This maneauver
11626    * allows to use the _G.resDirect flag later */
11627   pic16_aopOp(result,ic,TRUE);
11628   pic16_aopOp(right,ic,FALSE);
11629
11630   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11631
11632   /* if they are the same registers */
11633   if (pic16_sameRegs(AOP(right),AOP(result)))
11634     goto release;
11635
11636   /* if the result is a bit */
11637   if (AOP_TYPE(result) == AOP_CRY) {
11638     /* if the right size is a literal then
11639        we know what the value is */
11640     if (AOP_TYPE(right) == AOP_LIT) {
11641           
11642       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11643                   pic16_popGet(AOP(result),0));
11644
11645       if (((int) operandLitValue(right))) 
11646         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11647                        AOP(result)->aopu.aop_dir,
11648                        AOP(result)->aopu.aop_dir);
11649       else
11650         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11651                        AOP(result)->aopu.aop_dir,
11652                        AOP(result)->aopu.aop_dir);
11653       goto release;
11654     }
11655
11656     /* the right is also a bit variable */
11657     if (AOP_TYPE(right) == AOP_CRY) {
11658       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11659       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11660       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11661
11662       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11663                      AOP(result)->aopu.aop_dir,
11664                      AOP(result)->aopu.aop_dir);
11665       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11666                      AOP(right)->aopu.aop_dir,
11667                      AOP(right)->aopu.aop_dir);
11668       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11669                      AOP(result)->aopu.aop_dir,
11670                      AOP(result)->aopu.aop_dir);
11671       goto release ;
11672     }
11673
11674     /* we need to or */
11675     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11676     pic16_toBoolean(right);
11677     emitSKPZ;
11678     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11679     //pic16_aopPut(AOP(result),"a",0);
11680     goto release ;
11681   }
11682
11683   /* bit variables done */
11684   /* general case */
11685   size = AOP_SIZE(result);
11686   offset = 0 ;
11687
11688   if(AOP_TYPE(right) == AOP_LIT) {
11689         if(!IS_FLOAT(operandType( right )))
11690                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11691         else {
11692            union {
11693               unsigned long lit_int;
11694               float lit_float;
11695             } info;
11696         
11697                 /* take care if literal is a float */
11698                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11699                 lit = info.lit_int;
11700         }
11701   }
11702
11703 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11704 //                      sizeof(unsigned long int), sizeof(float));
11705
11706   if(AOP_TYPE(right) != AOP_LIT
11707         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
11708         && !IS_FUNC(OP_SYM_TYPE(right))
11709         ) {
11710         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11711 //      fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11712
11713         // set up table pointer
11714         if( (AOP_TYPE(right) == AOP_PCODE)
11715                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11716 //              || (AOP(right)->aopu.pcop->type == PO_DIR)
11717                 )
11718                 )
11719         {
11720 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11721                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11722                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11723                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11724                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11725                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11726                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11727         } else {
11728 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11729                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11730                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
11731                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11732                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
11733                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11734                                 pic16_popCopyReg(&pic16_pc_tblptru)));
11735         }
11736
11737         size = min(AOP_SIZE(right), AOP_SIZE(result));
11738         while(size--) {
11739                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11740                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11741                         pic16_popGet(AOP(result),offset)));
11742                 offset++;
11743         }
11744
11745         if(AOP_SIZE(result) > AOP_SIZE(right)) {
11746                 size = AOP_SIZE(result) - AOP_SIZE(right);
11747                 while(size--) {
11748                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11749                         offset++;
11750                 }
11751         }
11752         goto release;
11753   }
11754
11755
11756
11757 #if 0
11758 /* VR - What is this?! */
11759   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
11760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11761     if(aopIdx(AOP(result),0) == 4) {
11762
11763       /* this is a workaround to save value of right into wreg too,
11764        * value of wreg is going to be used later */
11765       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11766       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11767       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11768       goto release;
11769     } else
11770 //      assert(0);
11771       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
11772   }
11773 #endif
11774
11775   know_W=-1;
11776   while (size--) {
11777   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
11778     if(AOP_TYPE(right) == AOP_LIT) {
11779       if(lit&0xff) {
11780         if(know_W != (lit&0xff))
11781           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11782         know_W = lit&0xff;
11783         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11784       } else
11785         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11786
11787       lit >>= 8;
11788
11789     } else if (AOP_TYPE(right) == AOP_CRY) {
11790       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11791       if(offset == 0) {
11792         debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
11793         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11794         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11795       }
11796     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11797         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11798         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11799     } else {
11800       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11801
11802       if(!_G.resDirect)         /* use this aopForSym feature */
11803         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11804     }
11805             
11806     offset++;
11807   }
11808   
11809  release:
11810   pic16_freeAsmop (right,NULL,ic,FALSE);
11811   pic16_freeAsmop (result,NULL,ic,TRUE);
11812 }   
11813
11814 /*-----------------------------------------------------------------*/
11815 /* genJumpTab - generates code for jump table                       */
11816 /*-----------------------------------------------------------------*/
11817 static void genJumpTab (iCode *ic)
11818 {
11819     symbol *jtab;
11820     char *l;
11821
11822     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11823
11824     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11825     /* get the condition into accumulator */
11826     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11827     MOVA(l);
11828     /* multiply by three */
11829     pic16_emitcode("add","a,acc");
11830     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11831
11832     jtab = newiTempLabel(NULL);
11833     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11834     pic16_emitcode("jmp","@a+dptr");
11835     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11836
11837     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11838     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11839     emitSKPNC;
11840     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11841     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11842     pic16_emitpLabel(jtab->key);
11843
11844     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11845
11846     /* now generate the jump labels */
11847     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11848          jtab = setNextItem(IC_JTLABELS(ic))) {
11849         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11850         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11851         
11852     }
11853
11854 }
11855
11856 /*-----------------------------------------------------------------*/
11857 /* genMixedOperation - gen code for operators between mixed types  */
11858 /*-----------------------------------------------------------------*/
11859 /*
11860   TSD - Written for the PIC port - but this unfortunately is buggy.
11861   This routine is good in that it is able to efficiently promote 
11862   types to different (larger) sizes. Unfortunately, the temporary
11863   variables that are optimized out by this routine are sometimes
11864   used in other places. So until I know how to really parse the 
11865   iCode tree, I'm going to not be using this routine :(.
11866 */
11867 static int genMixedOperation (iCode *ic)
11868 {
11869 #if 0
11870   operand *result = IC_RESULT(ic);
11871   sym_link *ctype = operandType(IC_LEFT(ic));
11872   operand *right = IC_RIGHT(ic);
11873   int ret = 0;
11874   int big,small;
11875   int offset;
11876
11877   iCode *nextic;
11878   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11879
11880   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11881
11882   nextic = ic->next;
11883   if(!nextic)
11884     return 0;
11885
11886   nextright = IC_RIGHT(nextic);
11887   nextleft  = IC_LEFT(nextic);
11888   nextresult = IC_RESULT(nextic);
11889
11890   pic16_aopOp(right,ic,FALSE);
11891   pic16_aopOp(result,ic,FALSE);
11892   pic16_aopOp(nextright,  nextic, FALSE);
11893   pic16_aopOp(nextleft,   nextic, FALSE);
11894   pic16_aopOp(nextresult, nextic, FALSE);
11895
11896   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11897
11898     operand *t = right;
11899     right = nextright;
11900     nextright = t; 
11901
11902     pic16_emitcode(";remove right +","");
11903
11904   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11905 /*
11906     operand *t = right;
11907     right = nextleft;
11908     nextleft = t; 
11909 */
11910     pic16_emitcode(";remove left +","");
11911   } else
11912     return 0;
11913
11914   big = AOP_SIZE(nextleft);
11915   small = AOP_SIZE(nextright);
11916
11917   switch(nextic->op) {
11918
11919   case '+':
11920     pic16_emitcode(";optimize a +","");
11921     /* if unsigned or not an integral type */
11922     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11923       pic16_emitcode(";add a bit to something","");
11924     } else {
11925
11926       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11927
11928       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11929         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11930         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11931       } else
11932         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11933
11934       offset = 0;
11935       while(--big) {
11936
11937         offset++;
11938
11939         if(--small) {
11940           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11941             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11942             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11943           }
11944
11945           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11946           emitSKPNC;
11947           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11948                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11949                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11950           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11951           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11952
11953         } else {
11954           pic16_emitcode("rlf","known_zero,w");
11955
11956           /*
11957             if right is signed
11958               btfsc  right,7
11959                addlw ff
11960           */
11961           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11962             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11963             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11964           } else {
11965             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11966           }
11967         }
11968       }
11969       ret = 1;
11970     }
11971   }
11972   ret = 1;
11973
11974 release:
11975   pic16_freeAsmop(right,NULL,ic,TRUE);
11976   pic16_freeAsmop(result,NULL,ic,TRUE);
11977   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11978   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11979   if(ret)
11980     nextic->generated = 1;
11981
11982   return ret;
11983 #else
11984   return 0;
11985 #endif
11986 }
11987 /*-----------------------------------------------------------------*/
11988 /* genCast - gen code for casting                                  */
11989 /*-----------------------------------------------------------------*/
11990 static void genCast (iCode *ic)
11991 {
11992   operand *result = IC_RESULT(ic);
11993   sym_link *ctype = operandType(IC_LEFT(ic));
11994   sym_link *rtype = operandType(IC_RIGHT(ic));
11995   operand *right = IC_RIGHT(ic);
11996   int size, offset ;
11997
11998         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11999         /* if they are equivalent then do nothing */
12000         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12001                 return ;
12002
12003         pic16_aopOp(right,ic,FALSE) ;
12004         pic16_aopOp(result,ic,FALSE);
12005
12006         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12007
12008         /* if the result is a bit */
12009         if (AOP_TYPE(result) == AOP_CRY) {
12010         
12011                 /* if the right size is a literal then
12012                  * we know what the value is */
12013                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12014
12015                 if (AOP_TYPE(right) == AOP_LIT) {
12016                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12017                                 pic16_popGet(AOP(result),0));
12018
12019                         if (((int) operandLitValue(right))) 
12020                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12021                                         AOP(result)->aopu.aop_dir,
12022                                         AOP(result)->aopu.aop_dir);
12023                         else
12024                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12025                                         AOP(result)->aopu.aop_dir,
12026                                         AOP(result)->aopu.aop_dir);
12027                         goto release;
12028                 }
12029
12030                 /* the right is also a bit variable */
12031                 if (AOP_TYPE(right) == AOP_CRY) {
12032                         emitCLRC;
12033                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12034
12035                         pic16_emitcode("clrc","");
12036                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12037                                 AOP(right)->aopu.aop_dir,
12038                                 AOP(right)->aopu.aop_dir);
12039                         pic16_aopPut(AOP(result),"c",0);
12040                         goto release ;
12041                 }
12042
12043                 /* we need to or */
12044                 if (AOP_TYPE(right) == AOP_REG) {
12045                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12046                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12047                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12048                 }
12049                 pic16_toBoolean(right);
12050                 pic16_aopPut(AOP(result),"a",0);
12051                 goto release ;
12052         }
12053
12054         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12055           int offset = 1;
12056
12057                 size = AOP_SIZE(result);
12058
12059                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12060
12061                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12062                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12063                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12064
12065                 while (size--)
12066                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12067
12068                 goto release;
12069         }
12070
12071         /* if they are the same size : or less */
12072         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12073
12074                 /* if they are in the same place */
12075                 if (pic16_sameRegs(AOP(right),AOP(result)))
12076                         goto release;
12077
12078                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12079 #if 0
12080                 if (IS_PTR_CONST(rtype))
12081 #else
12082                 if (IS_CODEPTR(rtype))
12083 #endif
12084                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12085
12086 #if 0
12087                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12088 #else
12089                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12090 #endif
12091                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12092
12093 #if 0
12094                 if(AOP_TYPE(right) == AOP_IMMD) {
12095                   pCodeOp *pcop0, *pcop1, *pcop2;
12096                   symbol *sym = OP_SYMBOL( right );
12097
12098                         size = AOP_SIZE(result);
12099                         /* low */
12100                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12101                         /* high */
12102                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12103                         /* upper */
12104                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12105         
12106                         if (size == 3) {
12107                                 pic16_emitpcode(POC_MOVLW, pcop0);
12108                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12109                                 pic16_emitpcode(POC_MOVLW, pcop1);
12110                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12111                                 pic16_emitpcode(POC_MOVLW, pcop2);
12112                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12113                         } else
12114                         if (size == 2) {
12115                                 pic16_emitpcode(POC_MOVLW, pcop0);
12116                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12117                                 pic16_emitpcode(POC_MOVLW, pcop1);
12118                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12119                         } else {
12120                                 pic16_emitpcode(POC_MOVLW, pcop0);
12121                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12122                         }
12123                 } else
12124 #endif
12125                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12126                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12127                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12128                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12129                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12130                         if(AOP_SIZE(result) <2)
12131                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12132                 } else {
12133                         /* if they in different places then copy */
12134                         size = AOP_SIZE(result);
12135                         offset = 0 ;
12136                         while (size--) {
12137                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12138                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12139                                 offset++;
12140                         }
12141                 }
12142                 goto release;
12143         }
12144
12145         /* if the result is of type pointer */
12146         if (IS_PTR(ctype)) {
12147           int p_type;
12148           sym_link *type = operandType(right);
12149           sym_link *etype = getSpec(type);
12150
12151                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12152
12153                 /* pointer to generic pointer */
12154                 if (IS_GENPTR(ctype)) {
12155                   char *l = zero;
12156             
12157                         if (IS_PTR(type)) 
12158                                 p_type = DCL_TYPE(type);
12159                         else {
12160                 /* we have to go by the storage class */
12161                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12162
12163 /*              if (SPEC_OCLS(etype)->codesp )  */
12164 /*                  p_type = CPOINTER ;  */
12165 /*              else */
12166 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12167 /*                      p_type = FPOINTER ; */
12168 /*                  else */
12169 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12170 /*                          p_type = PPOINTER; */
12171 /*                      else */
12172 /*                          if (SPEC_OCLS(etype) == idata ) */
12173 /*                              p_type = IPOINTER ; */
12174 /*                          else */
12175 /*                              p_type = POINTER ; */
12176             }
12177                 
12178             /* the first two bytes are known */
12179       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12180             size = GPTRSIZE - 1; 
12181             offset = 0 ;
12182             while (size--) {
12183               if(offset < AOP_SIZE(right)) {
12184                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12185                 mov2f(AOP(result), AOP(right), offset);
12186 /*
12187                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12188                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12189                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12190                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12191                 } else { 
12192                   
12193                   pic16_aopPut(AOP(result),
12194                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12195                          offset);
12196                 }
12197 */
12198               } else 
12199                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12200               offset++;
12201             }
12202             /* the last byte depending on type */
12203             switch (p_type) {
12204             case IPOINTER:
12205             case POINTER:
12206                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12207                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12208 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12209                 break;
12210
12211             case CPOINTER:
12212                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12213                 break;
12214
12215             case FPOINTER:
12216               pic16_emitcode(";BUG!? ","%d",__LINE__);
12217                 l = one;
12218                 break;
12219             case PPOINTER:
12220               pic16_emitcode(";BUG!? ","%d",__LINE__);
12221                 l = "#0x03";
12222                 break;
12223
12224             case GPOINTER:
12225               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12226               break;
12227               
12228             default:
12229                 /* this should never happen */
12230                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12231                        "got unknown pointer type");
12232                 exit(1);
12233             }
12234             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12235             goto release ;
12236         }
12237         
12238         /* just copy the pointers */
12239         size = AOP_SIZE(result);
12240         offset = 0 ;
12241         while (size--) {
12242             pic16_aopPut(AOP(result),
12243                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12244                    offset);
12245             offset++;
12246         }
12247         goto release ;
12248     }
12249     
12250
12251
12252     /* so we now know that the size of destination is greater
12253     than the size of the source.
12254     Now, if the next iCode is an operator then we might be
12255     able to optimize the operation without performing a cast.
12256     */
12257     if(genMixedOperation(ic))
12258       goto release;
12259
12260     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12261     
12262     /* we move to result for the size of source */
12263     size = AOP_SIZE(right);
12264     offset = 0 ;
12265     while (size--) {
12266       mov2f(AOP(result), AOP(right), offset);
12267       offset++;
12268     }
12269
12270     /* now depending on the sign of the destination */
12271     size = AOP_SIZE(result) - AOP_SIZE(right);
12272     /* if unsigned or not an integral type */
12273     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12274       while (size--)
12275         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12276     } else {
12277       /* we need to extend the sign :( */
12278
12279       if(size == 1) {
12280         /* Save one instruction of casting char to int */
12281         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12282         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12283         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12284       } else {
12285         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12286
12287         if(offset)
12288           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12289         else
12290           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12291         
12292         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12293
12294         while (size--)
12295           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12296       }
12297     }
12298
12299 release:
12300     pic16_freeAsmop(right,NULL,ic,TRUE);
12301     pic16_freeAsmop(result,NULL,ic,TRUE);
12302
12303 }
12304
12305 /*-----------------------------------------------------------------*/
12306 /* genDjnz - generate decrement & jump if not zero instrucion      */
12307 /*-----------------------------------------------------------------*/
12308 static int genDjnz (iCode *ic, iCode *ifx)
12309 {
12310     symbol *lbl, *lbl1;
12311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12312
12313     if (!ifx)
12314         return 0;
12315     
12316     /* if the if condition has a false label
12317        then we cannot save */
12318     if (IC_FALSE(ifx))
12319         return 0;
12320
12321     /* if the minus is not of the form 
12322        a = a - 1 */
12323     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12324         !IS_OP_LITERAL(IC_RIGHT(ic)))
12325         return 0;
12326
12327     if (operandLitValue(IC_RIGHT(ic)) != 1)
12328         return 0;
12329
12330     /* if the size of this greater than one then no
12331        saving */
12332     if (getSize(operandType(IC_RESULT(ic))) > 1)
12333         return 0;
12334
12335     /* otherwise we can save BIG */
12336     lbl = newiTempLabel(NULL);
12337     lbl1= newiTempLabel(NULL);
12338
12339     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12340     
12341     if (IS_AOP_PREG(IC_RESULT(ic))) {
12342         pic16_emitcode("dec","%s",
12343                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12344         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12345         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12346     } else {    
12347
12348
12349       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12350       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12351
12352       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12353       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12354
12355     }
12356     
12357     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12358     ifx->generated = 1;
12359     return 1;
12360 }
12361
12362 /*-----------------------------------------------------------------*/
12363 /* genReceive - generate code for a receive iCode                  */
12364 /*-----------------------------------------------------------------*/
12365 static void genReceive (iCode *ic)
12366 {    
12367   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12368
12369 #if 0
12370   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12371         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12372 #endif
12373 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12374
12375   if (isOperandInFarSpace(IC_RESULT(ic))
12376       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12377           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12378
12379     int size = getSize(operandType(IC_RESULT(ic)));
12380     int offset =  pic16_fReturnSizePic - size;
12381
12382       assert( 0 );
12383       while (size--) {
12384         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12385                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12386                       offset++;
12387         }
12388
12389       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12390
12391       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12392       size = AOP_SIZE(IC_RESULT(ic));
12393       offset = 0;
12394       while (size--) {
12395         pic16_emitcode ("pop","acc");
12396         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12397       }
12398   } else {
12399     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12400
12401     _G.accInUse++;
12402     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12403     _G.accInUse--;
12404     assignResultValue(IC_RESULT(ic), 0);
12405   }
12406
12407   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12408 }
12409
12410 /*-----------------------------------------------------------------*/
12411 /* genDummyRead - generate code for dummy read of volatiles        */
12412 /*-----------------------------------------------------------------*/
12413 static void
12414 genDummyRead (iCode * ic)
12415 {
12416   pic16_emitcode ("; genDummyRead","");
12417   pic16_emitcode ("; not implemented","");
12418
12419   ic = ic;
12420 }
12421
12422 /*-----------------------------------------------------------------*/
12423 /* genpic16Code - generate code for pic16 based controllers        */
12424 /*-----------------------------------------------------------------*/
12425 /*
12426  * At this point, ralloc.c has gone through the iCode and attempted
12427  * to optimize in a way suitable for a PIC. Now we've got to generate
12428  * PIC instructions that correspond to the iCode.
12429  *
12430  * Once the instructions are generated, we'll pass through both the
12431  * peep hole optimizer and the pCode optimizer.
12432  *-----------------------------------------------------------------*/
12433
12434 void genpic16Code (iCode *lic)
12435 {
12436     iCode *ic;
12437     int cln = 0;
12438
12439     lineHead = lineCurr = NULL;
12440
12441     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12442     pic16_addpBlock(pb);
12443
12444 #if 0
12445     /* if debug information required */
12446     if (options.debug && currFunc) {
12447       if (currFunc) {
12448         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12449       }
12450     }
12451 #endif
12452
12453     for (ic = lic ; ic ; ic = ic->next ) {
12454
12455       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
12456         if ( cln != ic->lineno ) {
12457             if ( options.debug ) {
12458               debugFile->writeCLine (ic);
12459             }
12460             
12461             if(!options.noCcodeInAsm) {
12462                 pic16_addpCode2pBlock(pb,
12463                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
12464                                 printCLine(ic->filename, ic->lineno)));
12465             }
12466
12467             cln = ic->lineno ;
12468         }
12469         
12470         if(options.iCodeInAsm) {
12471                 char *l;
12472                 /* insert here code to print iCode as comment */
12473                 l = Safe_strdup(printILine(ic));
12474                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
12475         }
12476         
12477         /* if the result is marked as
12478            spilt and rematerializable or code for
12479            this has already been generated then
12480            do nothing */
12481         if (resultRemat(ic) || ic->generated ) 
12482             continue ;
12483         
12484         /* depending on the operation */
12485         switch (ic->op) {
12486         case '!' :
12487             pic16_genNot(ic);
12488             break;
12489             
12490         case '~' :
12491             pic16_genCpl(ic);
12492             break;
12493             
12494         case UNARYMINUS:
12495             genUminus (ic);
12496             break;
12497             
12498         case IPUSH:
12499             genIpush (ic);
12500             break;
12501             
12502         case IPOP:
12503             /* IPOP happens only when trying to restore a 
12504                spilt live range, if there is an ifx statement
12505                following this pop then the if statement might
12506                be using some of the registers being popped which
12507                would destroy the contents of the register so
12508                we need to check for this condition and handle it */
12509             if (ic->next            && 
12510                 ic->next->op == IFX &&
12511                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
12512                 genIfx (ic->next,ic);
12513             else
12514                 genIpop (ic);
12515             break; 
12516             
12517         case CALL:
12518             genCall (ic);
12519             break;
12520             
12521         case PCALL:
12522             genPcall (ic);
12523             break;
12524             
12525         case FUNCTION:
12526             genFunction (ic);
12527             break;
12528             
12529         case ENDFUNCTION:
12530             genEndFunction (ic);
12531             break;
12532             
12533         case RETURN:
12534             genRet (ic);
12535             break;
12536             
12537         case LABEL:
12538             genLabel (ic);
12539             break;
12540             
12541         case GOTO:
12542             genGoto (ic);
12543             break;
12544             
12545         case '+' :
12546             pic16_genPlus (ic) ;
12547             break;
12548             
12549         case '-' :
12550             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
12551                 pic16_genMinus (ic);
12552             break;
12553             
12554         case '*' :
12555             genMult (ic);
12556             break;
12557             
12558         case '/' :
12559             genDiv (ic) ;
12560             break;
12561             
12562         case '%' :
12563             genMod (ic);
12564             break;
12565             
12566         case '>' :
12567             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
12568             break;
12569             
12570         case '<' :
12571             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
12572             break;
12573             
12574         case LE_OP:
12575         case GE_OP:
12576         case NE_OP:
12577             
12578             /* note these two are xlated by algebraic equivalence
12579                during parsing SDCC.y */
12580             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12581                    "got '>=' or '<=' shouldn't have come here");
12582             break;      
12583             
12584         case EQ_OP:
12585             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
12586             break;          
12587             
12588         case AND_OP:
12589             genAndOp (ic);
12590             break;
12591             
12592         case OR_OP:
12593             genOrOp (ic);
12594             break;
12595             
12596         case '^' :
12597             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12598             break;
12599             
12600         case '|' :
12601                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12602             break;
12603             
12604         case BITWISEAND:
12605             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12606             break;
12607             
12608         case INLINEASM:
12609             genInline (ic);
12610             break;
12611             
12612         case RRC:
12613             genRRC (ic);
12614             break;
12615             
12616         case RLC:
12617             genRLC (ic);
12618             break;
12619             
12620         case GETHBIT:
12621             genGetHbit (ic);
12622             break;
12623             
12624         case LEFT_OP:
12625             genLeftShift (ic);
12626             break;
12627             
12628         case RIGHT_OP:
12629             genRightShift (ic);
12630             break;
12631             
12632         case GET_VALUE_AT_ADDRESS:
12633             genPointerGet(ic);
12634             break;
12635             
12636         case '=' :
12637             if (POINTER_SET(ic))
12638                 genPointerSet(ic);
12639             else
12640                 genAssign(ic);
12641             break;
12642             
12643         case IFX:
12644             genIfx (ic,NULL);
12645             break;
12646             
12647         case ADDRESS_OF:
12648             genAddrOf (ic);
12649             break;
12650             
12651         case JUMPTABLE:
12652             genJumpTab (ic);
12653             break;
12654             
12655         case CAST:
12656             genCast (ic);
12657             break;
12658             
12659         case RECEIVE:
12660             genReceive(ic);
12661             break;
12662             
12663         case SEND:
12664             addSet(&_G.sendSet,ic);
12665             /* create a reversed list of SEND iCodes */
12666 //            addSetHead(&_G.sendSet, ic);
12667             break;
12668
12669         case DUMMY_READ_VOLATILE:
12670           genDummyRead (ic);
12671           break;
12672
12673         default :
12674             ic = ic;
12675         }
12676     }
12677
12678
12679     /* now we are ready to call the
12680        peep hole optimizer */
12681     if (!options.nopeep) {
12682       peepHole (&lineHead);
12683     }
12684     /* now do the actual printing */
12685     printLine (lineHead, codeOutFile);
12686
12687 #ifdef PCODE_DEBUG
12688     DFPRINTF((stderr,"printing pBlock\n\n"));
12689     pic16_printpBlock(stdout,pb);
12690 #endif
12691
12692     return;
12693 }
12694