Large cummulative patch for pic16 port.
[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 extern set *externs;
76
77 /* max_key keeps track of the largest label number used in 
78    a function. This is then used to adjust the label offset
79    for the next function.
80 */
81 static int max_key=0;
82 static int GpsuedoStkPtr=0;
83
84 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
85
86 unsigned int pic16aopLiteral (value *val, int offset);
87 const char *pic16_AopType(short type);
88 static iCode *ifxForOp ( operand *op, iCode *ic );
89
90 void pic16_pushpCodeOp(pCodeOp *pcop);
91 void pic16_poppCodeOp(pCodeOp *pcop);
92
93 static bool is_LitOp(operand *op);
94 static bool is_LitAOp(asmop *aop);
95
96
97 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
98
99 /* set the following macro to 1 to enable passing the
100  * first byte of functions parameters via WREG */
101 #define USE_WREG_IN_FUNC_PARAMS 0
102
103
104 /* this is the down and dirty file with all kinds of 
105    kludgy & hacky stuff. This is what it is all about
106    CODE GENERATION for a specific MCU . some of the
107    routines may be reusable, will have to see */
108
109 static char *zero = "#0x00";
110 static char *one  = "#0x01";
111 //static char *spname = "sp";
112
113
114 /*
115  * Function return value policy (MSB-->LSB):
116  *  8 bits      -> WREG
117  * 16 bits      -> PRODL:WREG
118  * 24 bits      -> PRODH:PRODL:WREG
119  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
120  * >32 bits     -> on stack, and FSR0 points to the beginning
121  *
122  */
123  
124
125 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
126 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
127 static char **fReturn = fReturnpic16;
128
129 static char *accUse[] = {"WREG"};
130
131 //static short rbank = -1;
132
133 static struct {
134     short r0Pushed;
135     short r1Pushed;
136     short fsr0Pushed;
137     short accInUse;
138     short inLine;
139     short debugLine;
140     short nRegsSaved;
141     short ipushRegs;
142     set *sendSet;
143     set *stackRegSet;
144     int interruptvector;
145     int usefastretfie;
146     bitVect *fregsUsed;
147     int stack_lat;                      /* stack offset latency */
148     int resDirect;
149     int useWreg;                        /* flag when WREG is used to pass function parameter */
150 } _G;
151
152 /* Resolved ifx structure. This structure stores information
153    about an iCode ifx that makes it easier to generate code.
154 */
155 typedef struct resolvedIfx {
156   symbol *lbl;     /* pointer to a label */
157   int condition;   /* true or false ifx */
158   int generated;   /* set true when the code associated with the ifx
159                     * is generated */
160 } resolvedIfx;
161
162 extern int pic16_ptrRegReq ;
163 extern int pic16_nRegs;
164 extern FILE *codeOutFile;
165 //static void saverbank (int, iCode *,bool);
166
167 static lineNode *lineHead = NULL;
168 static lineNode *lineCurr = NULL;
169
170 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
171 0xE0, 0xC0, 0x80, 0x00};
172 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
173 0x07, 0x03, 0x01, 0x00};
174
175 static  pBlock *pb;
176
177 /*-----------------------------------------------------------------*/
178 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
179 /*                 exponent of 2 is returned, otherwise -1 is      */
180 /*                 returned.                                       */
181 /* note that this is similar to the function `powof2' in SDCCsymt  */
182 /* if(n == 2^y)                                                    */
183 /*   return y;                                                     */
184 /* return -1;                                                      */
185 /*-----------------------------------------------------------------*/
186 static int my_powof2 (unsigned long num)
187 {
188   if(num) {
189     if( (num & (num-1)) == 0) {
190       int nshifts = -1;
191       while(num) {
192         num>>=1;
193         nshifts++;
194       }
195       return nshifts;
196     }
197   }
198
199   return -1;
200 }
201
202 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
203 {
204   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
205                        line_no,
206                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
207                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
208                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
209                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
210                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
211                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
212                        ((result) ? AOP_SIZE(result) : 0));
213 }
214
215 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
216 {
217
218   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
219                        line_no,
220                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
221                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
222                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
223                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
224                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
225                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
226
227 }
228
229 void pic16_emitpcomment (char *fmt, ...)
230 {
231     va_list ap;
232     char lb[INITIAL_INLINEASM];  
233     char *lbp = lb;
234
235     va_start(ap,fmt);   
236
237     lb[0] = ';';
238     vsprintf(lb+1,fmt,ap);
239
240     while (isspace(*lbp)) lbp++;
241
242     if (lbp && *lbp) 
243         lineCurr = (lineCurr ?
244                     connectLine(lineCurr,newLineNode(lb)) :
245                     (lineHead = newLineNode(lb)));
246     lineCurr->isInline = _G.inLine;
247     lineCurr->isDebug  = _G.debugLine;
248
249     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
250     va_end(ap);
251
252 //      fprintf(stderr, "%s\n", lb);
253 }
254
255 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
256 {
257     va_list ap;
258     char lb[INITIAL_INLINEASM];  
259     char *lbp = lb;
260
261     if(!pic16_debug_verbose)
262       return;
263
264     va_start(ap,fmt);   
265
266     if (inst && *inst) {
267         if (fmt && *fmt)
268             sprintf(lb,"%s\t",inst);
269         else
270             sprintf(lb,"%s",inst);
271         vsprintf(lb+(strlen(lb)),fmt,ap);
272     }  else
273         vsprintf(lb,fmt,ap);
274
275     while (isspace(*lbp)) lbp++;
276
277     if (lbp && *lbp) 
278         lineCurr = (lineCurr ?
279                     connectLine(lineCurr,newLineNode(lb)) :
280                     (lineHead = newLineNode(lb)));
281     lineCurr->isInline = _G.inLine;
282     lineCurr->isDebug  = _G.debugLine;
283
284     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
285     va_end(ap);
286
287 //      fprintf(stderr, "%s\n", lb);
288 }
289
290 void pic16_emitpLabel(int key)
291 {
292   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
293 }
294
295 void pic16_emitpLabelFORCE(int key)
296 {
297   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
298 }
299
300 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
301 {
302
303   if(pcop)
304     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
305   else
306     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
307 }
308
309 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
310 {
311   if(pcop)
312     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
313   else
314     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
315 }
316   
317 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
318 {
319
320   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
321
322 }
323
324
325 #if 1
326 #define pic16_emitcode  DEBUGpic16_emitcode
327 #else
328 /*-----------------------------------------------------------------*/
329 /* pic16_emitcode - writes the code into a file : for now it is simple    */
330 /*-----------------------------------------------------------------*/
331 void pic16_emitcode (char *inst,char *fmt, ...)
332 {
333     va_list ap;
334     char lb[INITIAL_INLINEASM];  
335     char *lbp = lb;
336
337     va_start(ap,fmt);   
338
339     if (inst && *inst) {
340         if (fmt && *fmt)
341             sprintf(lb,"%s\t",inst);
342         else
343             sprintf(lb,"%s",inst);
344         vsprintf(lb+(strlen(lb)),fmt,ap);
345     }  else
346         vsprintf(lb,fmt,ap);
347
348     while (isspace(*lbp)) lbp++;
349
350     if (lbp && *lbp) 
351         lineCurr = (lineCurr ?
352                     connectLine(lineCurr,newLineNode(lb)) :
353                     (lineHead = newLineNode(lb)));
354     lineCurr->isInline = _G.inLine;
355     lineCurr->isDebug  = _G.debugLine;
356
357 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
358
359 //    if(pic16_debug_verbose)
360 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
361
362     va_end(ap);
363 }
364 #endif
365
366
367 /*-----------------------------------------------------------------*/
368 /* pic16_emitDebuggerSymbol - associate the current code location  */
369 /*   with a debugger symbol                                        */
370 /*-----------------------------------------------------------------*/
371 void
372 pic16_emitDebuggerSymbol (char * debugSym)
373 {
374   _G.debugLine = 1;
375   pic16_emitcode (";", "%s ==.", debugSym);
376   _G.debugLine = 0;
377 }
378
379
380 /*-----------------------------------------------------------------*/
381 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
382 /*-----------------------------------------------------------------*/
383 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
384 {
385 //    bool r0iu = FALSE , r1iu = FALSE;
386 //    bool r0ou = FALSE , r1ou = FALSE;
387     bool fsr0iu = FALSE, fsr0ou;
388     bool fsr2iu = FALSE, fsr2ou;
389     
390     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
391
392     
393     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
394     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
395     
396     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
397     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
398
399     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
400         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
401         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
402     }
403
404     if(!fsr0iu && !fsr0ou) {
405         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
406         (*aopp)->type = AOP_FSR0;
407
408         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
409         
410       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
411     }
412
413 #if 0
414     /* no usage of FSR2 */
415     if(!fsr2iu && !fsr2ou) {
416         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
417         (*aopp)->type = AOP_FSR2;
418
419       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
420     }
421 #endif
422         
423     /* now we know they both have usage */
424     /* if fsr0 not used in this instruction */
425     if (!fsr0iu) {
426         if (!_G.fsr0Pushed) {
427                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
428                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
429                 _G.fsr0Pushed++;
430         }
431
432         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
433         (*aopp)->type = AOP_FSR0;
434
435 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
436
437       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
438     }
439         
440
441     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
442     assert( 0 );
443
444     return NULL;
445 #if 0
446     /* the logic: if r0 & r1 used in the instruction
447     then we are in trouble otherwise */
448
449     /* first check if r0 & r1 are used by this
450     instruction, in which case we are in trouble */
451     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
452         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
453     {
454         goto endOfWorld;      
455     }
456
457     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
458     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
459
460     /* if no usage of r0 then return it */
461     if (!r0iu && !r0ou) {
462         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
463         (*aopp)->type = AOP_R0; 
464         
465         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
466     }
467
468     /* if no usage of r1 then return it */
469     if (!r1iu && !r1ou) {
470         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
471         (*aopp)->type = AOP_R1;
472
473         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
474     }    
475
476     /* now we know they both have usage */
477     /* if r0 not used in this instruction */
478     if (!r0iu) {
479         /* push it if not already pushed */
480         if (!_G.r0Pushed) {
481           //pic16_emitcode ("push","%s",
482           //          pic16_regWithIdx(R0_IDX)->dname);
483             _G.r0Pushed++ ;
484         }
485         
486         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
487         (*aopp)->type = AOP_R0;
488
489         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
490     }
491
492     /* if r1 not used then */
493
494     if (!r1iu) {
495         /* push it if not already pushed */
496         if (!_G.r1Pushed) {
497           //pic16_emitcode ("push","%s",
498           //          pic16_regWithIdx(R1_IDX)->dname);
499             _G.r1Pushed++ ;
500         }
501         
502         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
503         (*aopp)->type = AOP_R1;
504         return pic16_regWithIdx(R1_IDX);
505     }
506
507 endOfWorld :
508     /* I said end of world but not quite end of world yet */
509     /* if this is a result then we can push it on the stack*/
510     if (result) {
511         (*aopp)->type = AOP_STK;    
512         return NULL;
513     }
514
515     /* other wise this is true end of the world */
516     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
517            "getFreePtr should never reach here");
518     exit(0);
519 #endif
520 }
521
522 /*-----------------------------------------------------------------*/
523 /* newAsmop - creates a new asmOp                                  */
524 /*-----------------------------------------------------------------*/
525 static asmop *newAsmop (short type)
526 {
527     asmop *aop;
528
529     aop = Safe_calloc(1,sizeof(asmop));
530     aop->type = type;
531     return aop;
532 }
533
534 static void genSetDPTR(int n)
535 {
536     if (!n)
537     {
538         pic16_emitcode(";", "Select standard DPTR");
539         pic16_emitcode("mov", "dps, #0x00");
540     }
541     else
542     {
543         pic16_emitcode(";", "Select alternate DPTR");
544         pic16_emitcode("mov", "dps, #0x01");
545     }
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* resolveIfx - converts an iCode ifx into a form more useful for  */
550 /*              generating code                                    */
551 /*-----------------------------------------------------------------*/
552 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
553 {
554
555   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
556
557   if(!resIfx) 
558     return;
559
560
561   resIfx->condition = 1;    /* assume that the ifx is true */
562   resIfx->generated = 0;    /* indicate that the ifx has not been used */
563
564   if(!ifx) {
565     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
566
567 #if 1
568     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
569                         __FUNCTION__,__LINE__,resIfx->lbl->key);
570 #endif
571
572   } else {
573     if(IC_TRUE(ifx)) {
574       resIfx->lbl = IC_TRUE(ifx);
575     } else {
576       resIfx->lbl = IC_FALSE(ifx);
577       resIfx->condition = 0;
578     }
579
580 #if 1
581     if(IC_TRUE(ifx)) 
582       DEBUGpic16_emitcode("; +++","ifx true is non-null");
583     else
584       DEBUGpic16_emitcode("; +++","ifx true is null");
585     if(IC_FALSE(ifx)) 
586       DEBUGpic16_emitcode("; +++","ifx false is non-null");
587     else
588       DEBUGpic16_emitcode("; +++","ifx false is null");
589 #endif
590   }
591
592   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
593
594 }
595 #if 0
596 /*-----------------------------------------------------------------*/
597 /* pointerCode - returns the code for a pointer type               */
598 /*-----------------------------------------------------------------*/
599 static int pointerCode (sym_link *etype)
600 {
601
602     return PTR_TYPE(SPEC_OCLS(etype));
603
604 }
605 #endif
606
607 /*-----------------------------------------------------------------*/
608 /* aopForSym - for a true symbol                                   */
609 /*-----------------------------------------------------------------*/
610 static asmop *aopForSym (iCode *ic, operand *op, bool result)
611 {
612     symbol *sym=OP_SYMBOL(op);
613     asmop *aop;
614     memmap *space= SPEC_OCLS(sym->etype);
615
616     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
617
618     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
619     
620 //    sym = OP_SYMBOL(op);
621
622     /* if already has one */
623     if (sym->aop) {
624             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
625         return sym->aop;
626     }
627
628 #if 0
629     /* if symbol was initially placed onStack then we must re-place it
630      * to direct memory, since pic16 does not have a specific stack */
631     if(sym->onStack) {
632         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
633     }
634 #endif
635
636 #if 1
637     /* assign depending on the storage class */
638     /* if it is on the stack or indirectly addressable */
639     /* space we need to assign either r0 or r1 to it   */    
640     if (sym->onStack || sym->iaccess) {
641       pCodeOp *pcop[4];
642       int i;
643       
644         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
645                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
646         
647         /* acquire a temporary register -- it is saved in function */
648
649         sym->aop = aop = newAsmop(AOP_STA);
650         aop->aopu.stk.stk = sym->stack;
651         aop->size = getSize(sym->type);
652
653
654         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
655         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
656         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
657           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
658           
659           for(i=0;i<aop->size;i++)
660             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
661             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
662         } else
663           for(i=0;i<aop->size;i++) {
664             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
665             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
666           }
667
668
669 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
670
671 #if 1
672         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
673         
674         if(_G.accInUse) {
675                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
676         }
677         
678         for(i=0;i<aop->size;i++) {
679
680           /* initialise for stack access via frame pointer */
681           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
682
683           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
684                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
685         }
686         
687         if(_G.accInUse) {
688                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
689         }
690         
691         return (aop);
692 #endif
693
694 #if 0
695         /* now assign the address of the variable to 
696         the pointer register */
697         if (aop->type != AOP_STK) {
698
699             if (sym->onStack) {
700                     if ( _G.accInUse )
701                         pic16_emitcode("push","acc");
702
703                     pic16_emitcode("mov","a,_bp");
704                     pic16_emitcode("add","a,#0x%02x",
705                              ((sym->stack < 0) ?
706                               ((char)(sym->stack - _G.nRegsSaved )) :
707                               ((char)sym->stack)) & 0xff);
708                     pic16_emitcode("mov","%s,a",
709                              aop->aopu.aop_ptr->name);
710
711                     if ( _G.accInUse )
712                         pic16_emitcode("pop","acc");
713             } else
714                 pic16_emitcode("mov","%s,#%s",
715                          aop->aopu.aop_ptr->name,
716                          sym->rname);
717             aop->paged = space->paged;
718         } else
719             aop->aopu.aop_stk = sym->stack;
720         return aop;
721 #endif
722
723     }
724 #endif
725
726 #if 0
727     if (sym->onStack && options.stack10bit)
728     {
729         /* It's on the 10 bit stack, which is located in
730          * far data space.
731          */
732          
733       //DEBUGpic16_emitcode(";","%d",__LINE__);
734
735         if ( _G.accInUse )
736                 pic16_emitcode("push","acc");
737
738         pic16_emitcode("mov","a,_bp");
739         pic16_emitcode("add","a,#0x%02x",
740                  ((sym->stack < 0) ?
741                    ((char)(sym->stack - _G.nRegsSaved )) :
742                    ((char)sym->stack)) & 0xff);
743         
744         genSetDPTR(1);
745         pic16_emitcode ("mov","dpx1,#0x40");
746         pic16_emitcode ("mov","dph1,#0x00");
747         pic16_emitcode ("mov","dpl1, a");
748         genSetDPTR(0);
749         
750         if ( _G.accInUse )
751             pic16_emitcode("pop","acc");
752             
753         sym->aop = aop = newAsmop(AOP_DPTR2);
754         aop->size = getSize(sym->type); 
755         return aop;
756     }
757 #endif
758
759 #if 0
760     /* special case for a function */
761     if (IS_FUNC(sym->type)) {   
762         sym->aop = aop = newAsmop(AOP_PCODE);
763         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
764         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
765         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
766         PCOI(aop->aopu.pcop)->index = 0;
767         aop->size = FPTRSIZE; 
768         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
769         return aop;
770     }
771 #endif
772
773
774
775     //DEBUGpic16_emitcode(";","%d",__LINE__);
776     /* if in bit space */
777     if (IN_BITSPACE(space)) {
778         sym->aop = aop = newAsmop (AOP_CRY);
779         aop->aopu.aop_dir = sym->rname ;
780         aop->size = getSize(sym->type);
781         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
782         return aop;
783     }
784     /* if it is in direct space */
785     if (IN_DIRSPACE(space)) {
786         sym->aop = aop = newAsmop (AOP_DIR);
787         aop->aopu.aop_dir = sym->rname ;
788         aop->size = getSize(sym->type);
789         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
790         pic16_allocDirReg( IC_LEFT(ic) );
791         return aop;
792     }
793
794
795     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
796         sym->aop = aop = newAsmop (AOP_DIR);
797         aop->aopu.aop_dir = sym->rname ;
798         aop->size = getSize(sym->type);
799         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
800         pic16_allocDirReg( IC_LEFT(ic) );
801         return aop;
802     }
803
804
805     /* only remaining is far space */
806     sym->aop = aop = newAsmop(AOP_PCODE);
807
808 /* change the next if to 1 to revert to good old immediate code */
809         if(IN_CODESPACE(space)) {
810                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
811                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
812                 PCOI(aop->aopu.pcop)->index = 0;
813         } else {
814                 /* try to allocate via direct register */
815                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
816 //              aop->size = getSize( sym->type );
817         }
818
819         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
820                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
821
822 #if 0
823         if(!pic16_allocDirReg (IC_LEFT(ic)))
824                 return NULL;
825 #endif
826
827         if(IN_DIRSPACE( space ))
828                 aop->size = PTRSIZE;
829         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
830                 aop->size = FPTRSIZE;
831         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
832         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
833         else if(sym->onStack) {
834                 aop->size = PTRSIZE;
835         } else {
836                 assert( 0 );
837         }
838
839     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
840
841     /* if it is in code space */
842     if (IN_CODESPACE(space))
843         aop->code = 1;
844
845     return aop;     
846 }
847
848 /*-----------------------------------------------------------------*/
849 /* aopForRemat - rematerialzes an object                           */
850 /*-----------------------------------------------------------------*/
851 static asmop *aopForRemat (operand *op) // x symbol *sym)
852 {
853   symbol *sym = OP_SYMBOL(op);
854   operand *refop;
855   iCode *ic = NULL, *oldic;
856   asmop *aop = newAsmop(AOP_PCODE);
857   int val = 0;
858   int offset = 0;
859   int viaimmd=0;
860
861
862         ic = sym->rematiCode;
863
864         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
865         
866         if(IS_OP_POINTER(op)) {
867                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
868         }
869
870         for (;;) {
871                 oldic = ic;
872
873 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
874         
875                 if (ic->op == '+') {
876                         val += (int) operandLitValue(IC_RIGHT(ic));
877                 } else if (ic->op == '-') {
878                         val -= (int) operandLitValue(IC_RIGHT(ic));
879                 } else
880                         break;
881                 
882                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
883         }
884
885         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
886         refop = IC_LEFT(ic);
887
888         if(!op->isaddr)viaimmd++; else viaimmd=0;
889                 
890 /* set the following if to 1 to revert to good old immediate code */
891         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
892                 || viaimmd) {
893
894                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
895
896                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
897
898 #if 0
899                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
900 #else
901                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
902 #endif
903
904                 PCOI(aop->aopu.pcop)->index = val;
905                 
906                 aop->size = getSize( sym->type );
907         } else {
908                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
909
910                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
911                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
912
913                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
914         }
915
916
917         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
918                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
919 #if 0
920                 val, IS_PTR_CONST(operandType(op)));
921 #else
922                 val, IS_CODEPTR(operandType(op)));
923 #endif
924
925 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
926
927         pic16_allocDirReg (IC_LEFT(ic));
928
929         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
930                 aop->code = 1;
931
932   return aop;        
933 }
934
935 #if 0
936 static int aopIdx (asmop *aop, int offset)
937 {
938   if(!aop)
939     return -1;
940
941   if(aop->type !=  AOP_REG)
942     return -2;
943         
944   return aop->aopu.aop_reg[offset]->rIdx;
945
946 }
947 #endif
948
949 /*-----------------------------------------------------------------*/
950 /* regsInCommon - two operands have some registers in common       */
951 /*-----------------------------------------------------------------*/
952 static bool regsInCommon (operand *op1, operand *op2)
953 {
954     symbol *sym1, *sym2;
955     int i;
956
957     /* if they have registers in common */
958     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
959         return FALSE ;
960
961     sym1 = OP_SYMBOL(op1);
962     sym2 = OP_SYMBOL(op2);
963
964     if (sym1->nRegs == 0 || sym2->nRegs == 0)
965         return FALSE ;
966
967     for (i = 0 ; i < sym1->nRegs ; i++) {
968         int j;
969         if (!sym1->regs[i])
970             continue ;
971
972         for (j = 0 ; j < sym2->nRegs ;j++ ) {
973             if (!sym2->regs[j])
974                 continue ;
975
976             if (sym2->regs[j] == sym1->regs[i])
977                 return TRUE ;
978         }
979     }
980
981     return FALSE ;
982 }
983
984 /*-----------------------------------------------------------------*/
985 /* operandsEqu - equivalent                                        */
986 /*-----------------------------------------------------------------*/
987 static bool operandsEqu ( operand *op1, operand *op2)
988 {
989     symbol *sym1, *sym2;
990
991     /* if they not symbols */
992     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
993         return FALSE;
994
995     sym1 = OP_SYMBOL(op1);
996     sym2 = OP_SYMBOL(op2);
997
998     /* if both are itemps & one is spilt
999        and the other is not then false */
1000     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1001         sym1->isspilt != sym2->isspilt )
1002         return FALSE ;
1003
1004     /* if they are the same */
1005     if (sym1 == sym2)
1006         return TRUE ;
1007
1008     if (sym1->rname[0] && sym2->rname[0]
1009         && strcmp (sym1->rname, sym2->rname) == 0)
1010         return TRUE;
1011
1012
1013     /* if left is a tmp & right is not */
1014     if (IS_ITEMP(op1)  && 
1015         !IS_ITEMP(op2) &&
1016         sym1->isspilt  &&
1017         (sym1->usl.spillLoc == sym2))
1018         return TRUE;
1019
1020     if (IS_ITEMP(op2)  && 
1021         !IS_ITEMP(op1) &&
1022         sym2->isspilt  &&
1023         sym1->level > 0 &&
1024         (sym2->usl.spillLoc == sym1))
1025         return TRUE ;
1026
1027     return FALSE ;
1028 }
1029
1030 /*-----------------------------------------------------------------*/
1031 /* pic16_sameRegs - two asmops have the same registers                   */
1032 /*-----------------------------------------------------------------*/
1033 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1034 {
1035     int i;
1036
1037     if (aop1 == aop2)
1038         return TRUE ;
1039
1040     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1041                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1042
1043     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1044
1045     if (aop1->type != AOP_REG ||
1046         aop2->type != AOP_REG )
1047         return FALSE ;
1048
1049     if (aop1->size != aop2->size )
1050         return FALSE ;
1051
1052     for (i = 0 ; i < aop1->size ; i++ ) {
1053 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1054
1055 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1056         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1057             return FALSE ;
1058     }
1059
1060     return TRUE ;
1061 }
1062
1063 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1064 {
1065     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1066                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1067
1068     if(aop1 == aop2)return TRUE;
1069     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1070       
1071       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1072     
1073   return TRUE;
1074 }
1075
1076
1077 /*-----------------------------------------------------------------*/
1078 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1079 /*-----------------------------------------------------------------*/
1080 void pic16_aopOp (operand *op, iCode *ic, bool result)
1081 {
1082     asmop *aop;
1083     symbol *sym;
1084     int i;
1085
1086     if (!op)
1087         return ;
1088
1089     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1090
1091     /* if this a literal */
1092     if (IS_OP_LITERAL(op)) {
1093         op->aop = aop = newAsmop(AOP_LIT);
1094         aop->aopu.aop_lit = op->operand.valOperand;
1095         aop->size = getSize(operandType(op));
1096         return;
1097     }
1098
1099     {
1100       sym_link *type = operandType(op);
1101 #if 0
1102       if(IS_PTR_CONST(type))
1103 #else
1104       if(IS_CODEPTR(type))
1105 #endif
1106         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1107     }
1108
1109     /* if already has a asmop then continue */
1110     if (op->aop)
1111         return ;
1112
1113     /* if the underlying symbol has a aop */
1114     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1115       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1116         op->aop = OP_SYMBOL(op)->aop;
1117         return;
1118     }
1119
1120     /* if this is a true symbol */
1121     if (IS_TRUE_SYMOP(op)) {    
1122         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1123       op->aop = aopForSym(ic, op, result);
1124       return ;
1125     }
1126
1127     /* this is a temporary : this has
1128     only four choices :
1129     a) register
1130     b) spillocation
1131     c) rematerialize 
1132     d) conditional   
1133     e) can be a return use only */
1134
1135     sym = OP_SYMBOL(op);
1136
1137     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1138     /* if the type is a conditional */
1139     if (sym->regType == REG_CND) {
1140         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1141         aop->size = 0;
1142         return;
1143     }
1144
1145     /* if it is spilt then two situations
1146     a) is rematerialize 
1147     b) has a spill location */
1148     if (sym->isspilt || sym->nRegs == 0) {
1149
1150       DEBUGpic16_emitcode(";","%d",__LINE__);
1151         /* rematerialize it NOW */
1152         if (sym->remat) {
1153
1154             sym->aop = op->aop = aop = aopForRemat (op);
1155 //            aop->size = getSize(sym->type);
1156 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1157             return;
1158         }
1159
1160 #if 1
1161         if (sym->accuse) {
1162             int i;
1163             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1164             aop->size = getSize(sym->type);
1165             for ( i = 0 ; i < 1 ; i++ ) {
1166                 aop->aopu.aop_str[i] = accUse[i];
1167 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1168             }
1169             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1170             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1171             return;  
1172         }
1173 #endif
1174
1175 #if 1
1176         if (sym->ruonly ) {
1177           /*
1178           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1179           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1180           //pic16_allocDirReg (IC_LEFT(ic));
1181           aop->size = getSize(sym->type);
1182           */
1183
1184           unsigned i;
1185
1186           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1187           aop->size = getSize(sym->type);
1188           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1189             aop->aopu.aop_str[i] = fReturn[i];
1190
1191           DEBUGpic16_emitcode(";","%d",__LINE__);
1192           return;
1193         }
1194 #endif
1195         /* else spill location  */
1196         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1197             /* force a new aop if sizes differ */
1198             sym->usl.spillLoc->aop = NULL;
1199         }
1200
1201 #if 0
1202         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1203                             __FUNCTION__,__LINE__,
1204                             sym->usl.spillLoc->rname,
1205                             sym->rname, sym->usl.spillLoc->offset);
1206 #endif
1207
1208         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1209         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1210         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1211                                           getSize(sym->type), 
1212                                           sym->usl.spillLoc->offset, op);
1213         aop->size = getSize(sym->type);
1214
1215         return;
1216     }
1217
1218     {
1219       sym_link *type = operandType(op);
1220 #if 0
1221       if(IS_PTR_CONST(type)) 
1222 #else
1223       if(IS_CODEPTR(type)) 
1224 #endif
1225         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1226     }
1227
1228     /* must be in a register */
1229     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1230     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1231     aop->size = sym->nRegs;
1232     for ( i = 0 ; i < sym->nRegs ;i++)
1233         aop->aopu.aop_reg[i] = sym->regs[i];
1234 }
1235
1236 /*-----------------------------------------------------------------*/
1237 /* pic16_freeAsmop - free up the asmop given to an operand               */
1238 /*----------------------------------------------------------------*/
1239 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1240 {   
1241     asmop *aop ;
1242
1243     if (!op)
1244         aop = aaop;
1245     else 
1246         aop = op->aop;
1247
1248     if (!aop)
1249         return ;
1250
1251     if (aop->freed)
1252         goto dealloc; 
1253
1254     aop->freed = 1;
1255
1256     /* depending on the asmop type only three cases need work AOP_RO
1257        , AOP_R1 && AOP_STK */
1258 #if 1
1259     switch (aop->type) {
1260         case AOP_FSR0 :
1261             if (_G.fsr0Pushed ) {
1262                 if (pop) {
1263                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1264                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1265 //                    pic16_emitcode ("pop","ar0");
1266                     _G.fsr0Pushed--;
1267                 }
1268             }
1269             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1270             break;
1271
1272         case AOP_FSR2 :
1273             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1274             break;
1275
1276         case AOP_R0 :
1277             if (_G.r0Pushed ) {
1278                 if (pop) {
1279                     pic16_emitcode ("pop","ar0");     
1280                     _G.r0Pushed--;
1281                 }
1282             }
1283             bitVectUnSetBit(ic->rUsed,R0_IDX);
1284             break;
1285
1286         case AOP_R1 :
1287             if (_G.r1Pushed ) {
1288                 if (pop) {
1289                     pic16_emitcode ("pop","ar1");
1290                     _G.r1Pushed--;
1291                 }
1292             }
1293             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1294             break;
1295
1296         case AOP_STA:
1297           {
1298             int i;
1299
1300               /* we must store the result on stack */
1301               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1302                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1303                 for(i=0;i<aop->size;i++) {
1304                   /* initialise for stack access via frame pointer */
1305                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1306
1307                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1308                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1309                 }
1310         
1311                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1312               }
1313
1314               if(!_G.resDirect) {
1315                 for(i=0;i<aop->size;i++)
1316                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1317               }
1318               _G.resDirect = 0;
1319           }
1320           break;
1321 #if 0
1322         case AOP_STK :
1323         {
1324             int sz = aop->size;    
1325             int stk = aop->aopu.aop_stk + aop->size;
1326             bitVectUnSetBit(ic->rUsed,R0_IDX);
1327             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1328
1329             getFreePtr(ic,&aop,FALSE);
1330             
1331             if (options.stack10bit)
1332             {
1333                 /* I'm not sure what to do here yet... */
1334                 /* #STUB */
1335                 fprintf(stderr, 
1336                         "*** Warning: probably generating bad code for "
1337                         "10 bit stack mode.\n");
1338             }
1339             
1340             if (stk) {
1341                 pic16_emitcode ("mov","a,_bp");
1342                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1343                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1344             } else {
1345                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1346             }
1347
1348             while (sz--) {
1349                 pic16_emitcode("pop","acc");
1350                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1351                 if (!sz) break;
1352                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1353             }
1354             op->aop = aop;
1355             pic16_freeAsmop(op,NULL,ic,TRUE);
1356             if (_G.r0Pushed) {
1357                 pic16_emitcode("pop","ar0");
1358                 _G.r0Pushed--;
1359             }
1360
1361             if (_G.r1Pushed) {
1362                 pic16_emitcode("pop","ar1");
1363                 _G.r1Pushed--;
1364             }       
1365         }
1366 #endif
1367
1368     }
1369 #endif
1370
1371 dealloc:
1372     /* all other cases just dealloc */
1373     if (op ) {
1374         op->aop = NULL;
1375         if (IS_SYMOP(op)) {
1376             OP_SYMBOL(op)->aop = NULL;    
1377             /* if the symbol has a spill */
1378             if (SPIL_LOC(op))
1379                 SPIL_LOC(op)->aop = NULL;
1380         }
1381     }
1382 }
1383
1384 /*-----------------------------------------------------------------*/
1385 /* pic16_aopGet - for fetching value of the aop                          */
1386 /*-----------------------------------------------------------------*/
1387 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1388 {
1389     char *s = buffer ;
1390     char *rs;
1391
1392     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1393
1394     /* offset is greater than size then zero */
1395     if (offset > (aop->size - 1) &&
1396         aop->type != AOP_LIT)
1397         return zero;
1398
1399     /* depending on type */
1400     switch (aop->type) {
1401
1402     case AOP_FSR0:
1403     case AOP_FSR2:
1404       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1405       rs = Safe_calloc(1, strlen(s)+1);
1406       strcpy(rs, s);
1407       return (rs);
1408       
1409 #if 0
1410       /* if we need to increment it */
1411       while (offset > aop->coff)
1412         {
1413           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1414           aop->coff++;
1415         }
1416
1417       while (offset < aop->coff)
1418         {
1419           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1420           aop->coff--;
1421         }
1422       aop->coff = offset;
1423       if (aop->paged)
1424         {
1425           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1426           return (dname ? "acc" : "a");
1427         }
1428       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1429       rs = Safe_calloc (1, strlen (s) + 1);
1430       strcpy (rs, s);
1431       return rs;
1432 #endif
1433
1434         
1435     case AOP_IMMD:
1436         if (bit16) 
1437             sprintf (s,"%s",aop->aopu.aop_immd);
1438         else
1439             if (offset) 
1440                 sprintf(s,"(%s >> %d)",
1441                         aop->aopu.aop_immd,
1442                         offset*8);
1443             else
1444                 sprintf(s,"%s",
1445                         aop->aopu.aop_immd);
1446         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1447         rs = Safe_calloc(1,strlen(s)+1);
1448         strcpy(rs,s);   
1449         return rs;
1450         
1451     case AOP_DIR:
1452       if (offset) {
1453         sprintf(s,"(%s + %d)",
1454                 aop->aopu.aop_dir,
1455                 offset);
1456         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1457       } else
1458             sprintf(s,"%s",aop->aopu.aop_dir);
1459         rs = Safe_calloc(1,strlen(s)+1);
1460         strcpy(rs,s);   
1461         return rs;
1462         
1463     case AOP_REG:
1464       //if (dname) 
1465       //    return aop->aopu.aop_reg[offset]->dname;
1466       //else
1467             return aop->aopu.aop_reg[offset]->name;
1468         
1469     case AOP_CRY:
1470       //pic16_emitcode(";","%d",__LINE__);
1471       return aop->aopu.aop_dir;
1472         
1473     case AOP_ACC:
1474         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1475 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1476 //        assert( 0 );
1477 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1478         rs = Safe_strdup("WREG");
1479         return (rs);
1480
1481     case AOP_LIT:
1482         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1483         rs = Safe_calloc(1,strlen(s)+1);
1484         strcpy(rs,s);   
1485         return rs;
1486         
1487     case AOP_STR:
1488         aop->coff = offset ;
1489         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1490             dname)
1491             return "acc";
1492         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1493         
1494         return aop->aopu.aop_str[offset];
1495         
1496     case AOP_PCODE:
1497       {
1498         pCodeOp *pcop = aop->aopu.pcop;
1499         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1500         if(pcop->name) {
1501           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1502           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1503           sprintf(s,"%s", pcop->name);
1504         } else
1505           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1506
1507       }
1508       rs = Safe_calloc(1,strlen(s)+1);
1509       strcpy(rs,s);   
1510       return rs;
1511
1512     case AOP_STA:
1513         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1514         return (rs);
1515         
1516     case AOP_STK:
1517 //        pCodeOp *pcop = aop->aop
1518         break;
1519
1520     }
1521
1522     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1523     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1524            "aopget got unsupported aop->type");
1525     exit(0);
1526 }
1527
1528
1529
1530 /* lock has the following meaning: When allocating temporary registers
1531  * for stack variables storage, the value of the temporary register is
1532  * saved on stack. Its value is restored at the end. This procedure is
1533  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1534  * a possibility that before a call to pic16_aopOp, a temporary register
1535  * is allocated for a while and it is freed after some time, this will
1536  * mess the stack and values will not be restored properly. So use lock=1
1537  * to allocate temporary registers used internally by the programmer, and
1538  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1539  * to inform the compiler developer about a possible bug. This is an internal
1540  * feature for developing the compiler -- VR */
1541  
1542 int _TempReg_lock = 0;
1543 /*-----------------------------------------------------------------*/
1544 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1545 /*-----------------------------------------------------------------*/
1546 pCodeOp *pic16_popGetTempReg(int lock)
1547 {
1548   pCodeOp *pcop;
1549   symbol *cfunc;
1550
1551 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1552     if(_TempReg_lock) {
1553 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1554     }
1555     
1556     _TempReg_lock += lock;
1557     
1558     cfunc = currFunc;
1559     currFunc = NULL;
1560
1561     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1562     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1563       PCOR(pcop)->r->wasUsed=1;
1564       PCOR(pcop)->r->isFree=0;
1565
1566       /* push value on stack */
1567       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1568     }
1569
1570     currFunc = cfunc;
1571
1572   return pcop;
1573 }
1574
1575 /*-----------------------------------------------------------------*/
1576 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1577 /*                            don't save if inside v               */
1578 /*-----------------------------------------------------------------*/
1579 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1580 {
1581   pCodeOp *pcop;
1582   symbol *cfunc;
1583
1584 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1585
1586     if(_TempReg_lock) {
1587 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1588     }
1589
1590     _TempReg_lock += lock;
1591
1592     cfunc = currFunc;
1593     currFunc = NULL;
1594
1595     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1596     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597       PCOR(pcop)->r->wasUsed=1;
1598       PCOR(pcop)->r->isFree=0;
1599
1600       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1601       /* push value on stack */
1602         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1603       }
1604     }
1605
1606     currFunc = cfunc;
1607
1608   return pcop;
1609 }
1610
1611
1612 /*-----------------------------------------------------------------*/
1613 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1614 /*-----------------------------------------------------------------*/
1615 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1616 {
1617   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1618
1619   _TempReg_lock -= lock;
1620
1621   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1622     PCOR(pcop)->r->isFree = 1;
1623     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1624   }
1625 }
1626 /*-----------------------------------------------------------------*/
1627 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1628 /*-----------------------------------------------------------------*/
1629 pCodeOp *pic16_popGetLabel(unsigned int key)
1630 {
1631
1632   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1633
1634   if(key>max_key)
1635     max_key = key;
1636
1637   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1638 }
1639
1640 /*-----------------------------------------------------------------*/
1641 /* pic16_popCopyReg - copy a pcode operator                              */
1642 /*-----------------------------------------------------------------*/
1643 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1644 {
1645   pCodeOpReg *pcor;
1646
1647   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1648   pcor->pcop.type = pc->pcop.type;
1649   if(pc->pcop.name) {
1650     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1651       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1652   } else
1653     pcor->pcop.name = NULL;
1654
1655   pcor->r = pc->r;
1656   pcor->rIdx = pc->rIdx;
1657   pcor->r->wasUsed=1;
1658
1659 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1660
1661   return PCOP(pcor);
1662 }
1663
1664 /*-----------------------------------------------------------------*/
1665 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1666 /*-----------------------------------------------------------------*/
1667 pCodeOp *pic16_popGetLit(int lit)
1668 {
1669   return pic16_newpCodeOpLit(lit);
1670 }
1671
1672 /*-----------------------------------------------------------------*/
1673 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1674 /*-----------------------------------------------------------------*/
1675 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1676 {
1677   return pic16_newpCodeOpLit2(lit, arg2);
1678 }
1679
1680
1681 /*-----------------------------------------------------------------*/
1682 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1683 /*-----------------------------------------------------------------*/
1684 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1685 {
1686   return pic16_newpCodeOpImmd(name, offset,index, 0);
1687 }
1688
1689
1690 /*-----------------------------------------------------------------*/
1691 /* pic16_popGet - asm operator to pcode operator conversion              */
1692 /*-----------------------------------------------------------------*/
1693 pCodeOp *pic16_popGetWithString(char *str)
1694 {
1695   pCodeOp *pcop;
1696
1697
1698   if(!str) {
1699     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1700     exit (1);
1701   }
1702
1703   pcop = pic16_newpCodeOp(str,PO_STR);
1704
1705   return pcop;
1706 }
1707
1708 /*-----------------------------------------------------------------*/
1709 /* pic16_popRegFromString -                                        */
1710 /*-----------------------------------------------------------------*/
1711 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1712 {
1713
1714   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1715   pcop->type = PO_DIR;
1716
1717   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1718   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1719
1720   if(!str)
1721     str = "BAD_STRING";
1722
1723   pcop->name = Safe_calloc(1,strlen(str)+1);
1724   strcpy(pcop->name,str);
1725
1726   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1727
1728   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1729
1730   /* make sure that register doesn't exist,
1731    * and operand isn't NULL
1732    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1733   if((PCOR(pcop)->r == NULL) 
1734     && (op)
1735     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1736 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1737 //              __FUNCTION__, __LINE__, str, size, offset);
1738
1739     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1740     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1741
1742   }
1743   PCOR(pcop)->instance = offset;
1744
1745   return pcop;
1746 }
1747
1748 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1749 {
1750   pCodeOp *pcop;
1751
1752 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1753
1754         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1755         PCOR(pcop)->rIdx = rIdx;
1756         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1757
1758         PCOR(pcop)->r->isFree = 0;
1759         PCOR(pcop)->r->wasUsed = 1;
1760
1761         pcop->type = PCOR(pcop)->r->pc_type;
1762
1763   return pcop;
1764 }
1765
1766 /*---------------------------------------------------------------------------------*/
1767 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1768 /*                 VR 030601                                                       */
1769 /*---------------------------------------------------------------------------------*/
1770 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1771 {
1772   pCodeOpReg2 *pcop2;
1773   pCodeOp *temp;
1774   
1775         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1776
1777         /* comment the following check, so errors to throw up */
1778 //      if(!pcop2)return NULL;
1779
1780         temp = pic16_popGet(aop_dst, offset);
1781         pcop2->pcop2 = temp;
1782         
1783   return PCOP(pcop2);
1784 }
1785
1786
1787
1788 /*--------------------------------------------------------------------------------.-*/
1789 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1790 /*                  VR 030601 , adapted by Hans Dorn                                */
1791 /*--------------------------------------------------------------------------------.-*/
1792 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1793 {
1794   pCodeOpReg2 *pcop2;
1795  
1796         pcop2 = (pCodeOpReg2 *)src;
1797         pcop2->pcop2 = dst;
1798         
1799         return PCOP(pcop2);
1800 }
1801
1802
1803
1804 /*---------------------------------------------------------------------------------*/
1805 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1806 /*                     movff instruction                                           */
1807 /*---------------------------------------------------------------------------------*/
1808 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1809 {
1810   pCodeOpReg2 *pcop2;
1811
1812         if(!noalloc) {
1813                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1814                 pcop2->pcop2 = pic16_popCopyReg(dst);
1815         } else {
1816                 /* the pCodeOp may be already allocated */
1817                 pcop2 = (pCodeOpReg2 *)(src);
1818                 pcop2->pcop2 = (pCodeOp *)(dst);
1819         }
1820
1821   return PCOP(pcop2);
1822 }
1823
1824
1825 /*-----------------------------------------------------------------*/
1826 /* pic16_popGet - asm operator to pcode operator conversion              */
1827 /*-----------------------------------------------------------------*/
1828 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1829 {
1830   //char *s = buffer ;
1831   char *rs;
1832   pCodeOp *pcop;
1833
1834     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1835     /* offset is greater than
1836     size then zero */
1837
1838 //    if (offset > (aop->size - 1) &&
1839 //        aop->type != AOP_LIT)
1840 //      return NULL;  //zero;
1841
1842     /* depending on type */
1843     switch (aop->type) {
1844         
1845     case AOP_R0:
1846     case AOP_R1:
1847     case AOP_DPTR:
1848     case AOP_DPTR2:
1849         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1850         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1851         assert( 0 );
1852         return NULL;
1853
1854
1855     case AOP_FSR0:
1856     case AOP_FSR2:
1857       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1858       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1859       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1860       PCOR(pcop)->r->wasUsed = 1;
1861       PCOR(pcop)->r->isFree = 0;
1862       
1863       PCOR(pcop)->instance = offset;
1864       pcop->type = PCOR(pcop)->r->pc_type;
1865       return (pcop);
1866
1867     case AOP_IMMD:
1868       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1869       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1870
1871     case AOP_STA:
1872       /* pCodeOp is already allocated from aopForSym */
1873         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1874         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1875           
1876       return (pcop);
1877       
1878     case AOP_ACC:
1879       {
1880         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1881
1882         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1883
1884         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1885         
1886         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1887         PCOR(pcop)->rIdx = rIdx;
1888         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1889         PCOR(pcop)->r->wasUsed=1;
1890         PCOR(pcop)->r->isFree=0;
1891
1892         PCOR(pcop)->instance = offset;
1893         pcop->type = PCOR(pcop)->r->pc_type;
1894 //      rs = aop->aopu.aop_reg[offset]->name;
1895 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1896         return pcop;
1897
1898
1899 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1900 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1901
1902 //      assert( 0 );
1903       }
1904         
1905     case AOP_DIR:
1906       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1907       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1908         
1909     case AOP_REG:
1910       {
1911         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1912
1913         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1914         
1915         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1916 //      pcop->type = PO_GPR_REGISTER;
1917         PCOR(pcop)->rIdx = rIdx;
1918         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1919         PCOR(pcop)->r->wasUsed=1;
1920         PCOR(pcop)->r->isFree=0;
1921
1922         PCOR(pcop)->instance = offset;
1923         pcop->type = PCOR(pcop)->r->pc_type;
1924         
1925         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1926         rs = aop->aopu.aop_reg[offset]->name;
1927         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1928         return pcop;
1929       }
1930
1931     case AOP_CRY:
1932         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1933
1934       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1935       PCOR(pcop)->instance = offset;
1936       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1937       //if(PCOR(pcop)->r == NULL)
1938       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1939       return pcop;
1940         
1941     case AOP_LIT:
1942         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1943       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1944
1945     case AOP_STR:
1946       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1947       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1948
1949       /*
1950       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1951       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1952       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1953       pcop->type = PCOR(pcop)->r->pc_type;
1954       pcop->name = PCOR(pcop)->r->name;
1955
1956       return pcop;
1957       */
1958
1959     case AOP_PCODE:
1960       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1961                           __LINE__, 
1962                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1963       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1964 #if 1
1965         switch( aop->aopu.pcop->type ) {
1966                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1967                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1968                 default:
1969                         assert( 0 );    /* should never reach here */;
1970         }
1971 #else
1972       PCOI(pcop)->offset = offset;
1973 #endif
1974       return pcop;
1975     }
1976
1977     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1978            "pic16_popGet got unsupported aop->type");
1979     exit(0);
1980 }
1981 /*-----------------------------------------------------------------*/
1982 /* pic16_aopPut - puts a string for a aop                                */
1983 /*-----------------------------------------------------------------*/
1984 void pic16_aopPut (asmop *aop, char *s, int offset)
1985 {
1986     char *d = buffer ;
1987     symbol *lbl ;
1988
1989     return;
1990
1991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1992
1993     if (aop->size && offset > ( aop->size - 1)) {
1994         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1995                "pic16_aopPut got offset > aop->size");
1996         exit(0);
1997     }
1998
1999     /* will assign value to value */
2000     /* depending on where it is ofcourse */
2001     switch (aop->type) {
2002     case AOP_DIR:
2003       if (offset) {
2004         sprintf(d,"(%s + %d)",
2005                 aop->aopu.aop_dir,offset);
2006         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2007
2008       } else
2009             sprintf(d,"%s",aop->aopu.aop_dir);
2010         
2011         if (strcmp(d,s)) {
2012           DEBUGpic16_emitcode(";","%d",__LINE__);
2013           if(strcmp(s,"W"))
2014             pic16_emitcode("movf","%s,w",s);
2015           pic16_emitcode("movwf","%s",d);
2016
2017           if(strcmp(s,"W")) {
2018             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2019             if(offset >= aop->size) {
2020               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2021               break;
2022             } else
2023               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2024           }
2025
2026           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2027
2028
2029         }
2030         break;
2031         
2032     case AOP_REG:
2033       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2034         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2035           /*
2036             if (*s == '@'           ||
2037                 strcmp(s,"r0") == 0 ||
2038                 strcmp(s,"r1") == 0 ||
2039                 strcmp(s,"r2") == 0 ||
2040                 strcmp(s,"r3") == 0 ||
2041                 strcmp(s,"r4") == 0 ||
2042                 strcmp(s,"r5") == 0 ||
2043                 strcmp(s,"r6") == 0 || 
2044                 strcmp(s,"r7") == 0 )
2045                 pic16_emitcode("mov","%s,%s  ; %d",
2046                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2047             else
2048           */
2049
2050           if(strcmp(s,"W")==0 )
2051             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2052
2053           pic16_emitcode("movwf","%s",
2054                    aop->aopu.aop_reg[offset]->name);
2055
2056           if(strcmp(s,zero)==0) {
2057             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2058
2059           } else if(strcmp(s,"W")==0) {
2060             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2061             pcop->type = PO_GPR_REGISTER;
2062
2063             PCOR(pcop)->rIdx = -1;
2064             PCOR(pcop)->r = NULL;
2065
2066             DEBUGpic16_emitcode(";","%d",__LINE__);
2067             pcop->name = Safe_strdup(s);
2068             pic16_emitpcode(POC_MOVFW,pcop);
2069             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2070           } else if(strcmp(s,one)==0) {
2071             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2072             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2073           } else {
2074             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2075           }
2076         }
2077         break;
2078         
2079     case AOP_DPTR:
2080     case AOP_DPTR2:
2081     
2082     if (aop->type == AOP_DPTR2)
2083     {
2084         genSetDPTR(1);
2085     }
2086     
2087         if (aop->code) {
2088             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2089                    "pic16_aopPut writting to code space");
2090             exit(0);
2091         }
2092         
2093         while (offset > aop->coff) {
2094             aop->coff++;
2095             pic16_emitcode ("inc","dptr");
2096         }
2097         
2098         while (offset < aop->coff) {
2099             aop->coff-- ;
2100             pic16_emitcode("lcall","__decdptr");
2101         }
2102         
2103         aop->coff = offset;
2104         
2105         /* if not in accumulater */
2106         MOVA(s);        
2107         
2108         pic16_emitcode ("movx","@dptr,a");
2109         
2110     if (aop->type == AOP_DPTR2)
2111     {
2112         genSetDPTR(0);
2113     }
2114         break;
2115         
2116     case AOP_R0:
2117     case AOP_R1:
2118         while (offset > aop->coff) {
2119             aop->coff++;
2120             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2121         }
2122         while (offset < aop->coff) {
2123             aop->coff-- ;
2124             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2125         }
2126         aop->coff = offset;
2127         
2128         if (aop->paged) {
2129             MOVA(s);           
2130             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2131             
2132         } else
2133             if (*s == '@') {
2134                 MOVA(s);
2135                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2136             } else
2137                 if (strcmp(s,"r0") == 0 ||
2138                     strcmp(s,"r1") == 0 ||
2139                     strcmp(s,"r2") == 0 ||
2140                     strcmp(s,"r3") == 0 ||
2141                     strcmp(s,"r4") == 0 ||
2142                     strcmp(s,"r5") == 0 ||
2143                     strcmp(s,"r6") == 0 || 
2144                     strcmp(s,"r7") == 0 ) {
2145                     char buffer[10];
2146                     sprintf(buffer,"a%s",s);
2147                     pic16_emitcode("mov","@%s,%s",
2148                              aop->aopu.aop_ptr->name,buffer);
2149                 } else
2150                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2151         
2152         break;
2153         
2154     case AOP_STK:
2155         if (strcmp(s,"a") == 0)
2156             pic16_emitcode("push","acc");
2157         else
2158             pic16_emitcode("push","%s",s);
2159         
2160         break;
2161         
2162     case AOP_CRY:
2163         /* if bit variable */
2164         if (!aop->aopu.aop_dir) {
2165             pic16_emitcode("clr","a");
2166             pic16_emitcode("rlc","a");
2167         } else {
2168             if (s == zero) 
2169                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2170             else
2171                 if (s == one)
2172                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2173                 else
2174                     if (!strcmp(s,"c"))
2175                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2176                     else {
2177                         lbl = newiTempLabel(NULL);
2178                         
2179                         if (strcmp(s,"a")) {
2180                             MOVA(s);
2181                         }
2182                         pic16_emitcode("clr","c");
2183                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2184                         pic16_emitcode("cpl","c");
2185                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2186                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2187                     }
2188         }
2189         break;
2190         
2191     case AOP_STR:
2192         aop->coff = offset;
2193         if (strcmp(aop->aopu.aop_str[offset],s))
2194             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2195         break;
2196         
2197     case AOP_ACC:
2198         aop->coff = offset;
2199         if (!offset && (strcmp(s,"acc") == 0))
2200             break;
2201         
2202         if (strcmp(aop->aopu.aop_str[offset],s))
2203             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2204         break;
2205
2206     default :
2207         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2208 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2209 //             "pic16_aopPut got unsupported aop->type");
2210 //      exit(0);    
2211     }    
2212
2213 }
2214
2215 /*-----------------------------------------------------------------*/
2216 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2217 /*-----------------------------------------------------------------*/
2218 static void mov2w (asmop *aop, int offset)
2219 {
2220   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2221
2222   if(is_LitAOp(aop))
2223     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2224   else
2225     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2226 }
2227
2228 static void mov2f(asmop *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, pic16_popGet(dst, offset));
2233   } else {
2234     if(pic16_sameRegsOfs(src, dst, offset))return;
2235     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2236                       pic16_popGet(dst, offset)));
2237   }
2238 }
2239
2240 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2241 {
2242   if(is_LitAOp(src)) {
2243     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2244     pic16_emitpcode(POC_MOVWF, dst);
2245   } else {
2246     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2247   }
2248 }
2249
2250 void pic16_testStackOverflow(void)
2251 {
2252 #define GSTACK_TEST_NAME        "__gstack_test"
2253
2254   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2255   
2256   {
2257     symbol *sym;
2258
2259       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2260       strcpy(sym->rname, GSTACK_TEST_NAME);
2261       checkAddSym(&externs, sym);
2262   }
2263
2264 }
2265
2266 /* push pcop into stack */
2267 void pic16_pushpCodeOp(pCodeOp *pcop)
2268 {
2269 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2270   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2271   if(pic16_options.gstack)
2272     pic16_testStackOverflow();
2273     
2274 }
2275
2276 /* pop pcop from stack */
2277 void pic16_poppCodeOp(pCodeOp *pcop)
2278 {
2279   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2280   if(pic16_options.gstack)
2281     pic16_testStackOverflow();
2282 }
2283
2284
2285 /*-----------------------------------------------------------------*/
2286 /* pushw - pushes wreg to stack                                    */
2287 /*-----------------------------------------------------------------*/
2288 void pushw(void)
2289 {
2290   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2291   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2292   if(pic16_options.gstack)
2293     pic16_testStackOverflow();
2294 }
2295
2296                 
2297 /*-----------------------------------------------------------------*/
2298 /* pushaop - pushes aop to stack                                   */
2299 /*-----------------------------------------------------------------*/
2300 void pushaop(asmop *aop, int offset)
2301 {
2302   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2303
2304   if(is_LitAOp(aop)) {
2305     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2306     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2307   } else {
2308     pic16_emitpcode(POC_MOVFF,
2309       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2310   }
2311
2312 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2313   if(pic16_options.gstack)
2314     pic16_testStackOverflow();
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* popaop - pops aop from stack                                    */
2319 /*-----------------------------------------------------------------*/
2320 void popaop(asmop *aop, int offset)
2321 {
2322   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2323   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2324   if(pic16_options.gstack)
2325     pic16_testStackOverflow();
2326 }
2327
2328 void popaopidx(asmop *aop, int offset, int index)
2329 {
2330   int ofs=1;
2331
2332     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2333
2334     if(STACK_MODEL_LARGE)ofs++;
2335
2336     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2337     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2338     if(pic16_options.gstack)
2339       pic16_testStackOverflow();
2340 }
2341
2342 /*-----------------------------------------------------------------*/
2343 /* reAdjustPreg - points a register back to where it should        */
2344 /*-----------------------------------------------------------------*/
2345 static void reAdjustPreg (asmop *aop)
2346 {
2347     int size ;
2348
2349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2350     aop->coff = 0;
2351     if ((size = aop->size) <= 1)
2352         return ;
2353     size-- ;
2354     switch (aop->type) {
2355         case AOP_R0 :
2356         case AOP_R1 :
2357             while (size--)
2358                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2359             break;          
2360         case AOP_DPTR :
2361         case AOP_DPTR2:
2362             if (aop->type == AOP_DPTR2)
2363             {
2364                 genSetDPTR(1);
2365             } 
2366             while (size--)
2367             {
2368                 pic16_emitcode("lcall","__decdptr");
2369             }
2370                 
2371             if (aop->type == AOP_DPTR2)
2372             {
2373                 genSetDPTR(0);
2374             }                
2375             break;  
2376
2377     }   
2378
2379 }
2380
2381
2382 #if 0
2383 /*-----------------------------------------------------------------*/
2384 /* opIsGptr: returns non-zero if the passed operand is             */   
2385 /* a generic pointer type.                                         */
2386 /*-----------------------------------------------------------------*/ 
2387 static int opIsGptr(operand *op)
2388 {
2389     sym_link *type = operandType(op);
2390     
2391     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2392     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2393     {
2394         return 1;
2395     }
2396     return 0;        
2397 }
2398 #endif
2399
2400 /*-----------------------------------------------------------------*/
2401 /* pic16_getDataSize - get the operand data size                         */
2402 /*-----------------------------------------------------------------*/
2403 int pic16_getDataSize(operand *op)
2404 {
2405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406
2407
2408     return AOP_SIZE(op);
2409
2410     // tsd- in the pic port, the genptr size is 1, so this code here
2411     // fails. ( in the 8051 port, the size was 4).
2412 #if 0
2413     int size;
2414     size = AOP_SIZE(op);
2415     if (size == GPTRSIZE)
2416     {
2417         sym_link *type = operandType(op);
2418         if (IS_GENPTR(type))
2419         {
2420             /* generic pointer; arithmetic operations
2421              * should ignore the high byte (pointer type).
2422              */
2423             size--;
2424     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2425         }
2426     }
2427     return size;
2428 #endif
2429 }
2430
2431 /*-----------------------------------------------------------------*/
2432 /* pic16_outAcc - output Acc                                             */
2433 /*-----------------------------------------------------------------*/
2434 void pic16_outAcc(operand *result)
2435 {
2436   int size,offset;
2437   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2438   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2439
2440
2441   size = pic16_getDataSize(result);
2442   if(size){
2443     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2444     size--;
2445     offset = 1;
2446     /* unsigned or positive */
2447     while(size--)
2448       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2449   }
2450
2451 }
2452
2453 /*-----------------------------------------------------------------*/
2454 /* pic16_outBitC - output a bit C                                  */
2455 /*                 Move to result the value of Carry flag -- VR    */
2456 /*-----------------------------------------------------------------*/
2457 void pic16_outBitC(operand *result)
2458 {
2459   int i;
2460
2461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2462
2463     /* if the result is bit */
2464     if (AOP_TYPE(result) == AOP_CRY) {
2465         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2466         pic16_aopPut(AOP(result),"c",0);
2467     } else {
2468
2469         i = AOP_SIZE(result);
2470         while(i--) {
2471                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2472         }
2473         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2474     }
2475 }
2476
2477 /*-----------------------------------------------------------------*/
2478 /* pic16_outBitOp - output a bit from Op                           */
2479 /*                 Move to result the value of set/clr op -- VR    */
2480 /*-----------------------------------------------------------------*/
2481 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2482 {
2483   int i;
2484
2485     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2486
2487     /* if the result is bit */
2488     if (AOP_TYPE(result) == AOP_CRY) {
2489         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2490         pic16_aopPut(AOP(result),"c",0);
2491     } else {
2492
2493         i = AOP_SIZE(result);
2494         while(i--) {
2495                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2496         }
2497         pic16_emitpcode(POC_RRCF, pcop);          
2498         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2499     }
2500 }
2501
2502 /*-----------------------------------------------------------------*/
2503 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2504 /*-----------------------------------------------------------------*/
2505 void pic16_toBoolean(operand *oper)
2506 {
2507     int size = AOP_SIZE(oper) - 1;
2508     int offset = 1;
2509
2510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511
2512     if ( AOP_TYPE(oper) != AOP_ACC) {
2513       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2514     }
2515     while (size--) {
2516       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2517     }
2518 }
2519
2520
2521 #if !defined(GEN_Not)
2522 /*-----------------------------------------------------------------*/
2523 /* genNot - generate code for ! operation                          */
2524 /*-----------------------------------------------------------------*/
2525 static void pic16_genNot (iCode *ic)
2526 {
2527   symbol *tlbl;
2528   int size;
2529
2530   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2531   /* assign asmOps to operand & result */
2532   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2533   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2534
2535   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2536   /* if in bit space then a special case */
2537   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2538     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2539       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2540       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2541     } else {
2542       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2543       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2544       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2545     }
2546     goto release;
2547   }
2548
2549   size = AOP_SIZE(IC_LEFT(ic));
2550   if(size == 1) {
2551     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2552     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2553     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2554     goto release;
2555   }
2556   pic16_toBoolean(IC_LEFT(ic));
2557
2558   tlbl = newiTempLabel(NULL);
2559   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2560   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2561   pic16_outBitC(IC_RESULT(ic));
2562
2563  release:    
2564   /* release the aops */
2565   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2566   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2567 }
2568 #endif
2569
2570
2571 #if !defined(GEN_Cpl)
2572 /*-----------------------------------------------------------------*/
2573 /* genCpl - generate code for complement                           */
2574 /*-----------------------------------------------------------------*/
2575 static void pic16_genCpl (iCode *ic)
2576 {
2577     int offset = 0;
2578     int size ;
2579
2580
2581     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2582     /* assign asmOps to operand & result */
2583     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2584     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2585
2586     /* if both are in bit space then 
2587     a special case */
2588     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2589         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2590
2591         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2592         pic16_emitcode("cpl","c"); 
2593         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2594         goto release; 
2595     } 
2596
2597     size = AOP_SIZE(IC_RESULT(ic));
2598     while (size--) {
2599 /*
2600         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2601         MOVA(l);       
2602         pic16_emitcode("cpl","a");
2603         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2604 */
2605         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2606               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2607         } else {
2608                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2609                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2610         }
2611         offset++;
2612
2613     }
2614
2615
2616 release:
2617     /* release the aops */
2618     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2619     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2620 }
2621 #endif
2622
2623 /*-----------------------------------------------------------------*/
2624 /* genUminusFloat - unary minus for floating points                */
2625 /*-----------------------------------------------------------------*/
2626 static void genUminusFloat(operand *op,operand *result)
2627 {
2628     int size ,offset =0 ;
2629
2630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2631     /* for this we just need to flip the 
2632     first it then copy the rest in place */
2633     size = AOP_SIZE(op);
2634
2635     while(size--) {
2636       mov2f(AOP(result), AOP(op), offset);
2637       offset++;
2638     }
2639     
2640     /* toggle the MSB's highest bit */
2641     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2642 }
2643
2644 /*-----------------------------------------------------------------*/
2645 /* genUminus - unary minus code generation                         */
2646 /*-----------------------------------------------------------------*/
2647 static void genUminus (iCode *ic)
2648 {
2649   int size, i;
2650   sym_link *optype, *rtype;
2651
2652         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2653         
2654         /* assign asmops */
2655         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2656         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2657
2658         /* if both in bit space then special case */
2659         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2660                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2661
2662                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2663                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2664                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2665                 
2666                 goto release; 
2667         } 
2668
2669         optype = operandType(IC_LEFT(ic));
2670         rtype = operandType(IC_RESULT(ic));
2671
2672         /* if float then do float stuff */
2673         if (IS_FLOAT(optype)) {
2674                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2675                 goto release;
2676         }
2677
2678         /* otherwise subtract from zero by taking the 2's complement */
2679         size = AOP_SIZE(IC_LEFT(ic));
2680
2681         for(i=0; i<size; i++) {
2682                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2683                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2684                 else {
2685                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2686                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2687                 }
2688         }
2689
2690         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2691         for(i=1; i<size; i++) {
2692                 emitSKPNZ;
2693                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2694         }
2695
2696 release:
2697         /* release the aops */
2698         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2699         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2700 }
2701
2702 #if 0
2703 /*-----------------------------------------------------------------*/
2704 /* saveRegisters - will look for a call and save the registers     */
2705 /*-----------------------------------------------------------------*/
2706 static void saveRegisters(iCode *lic) 
2707 {
2708     int i;
2709     iCode *ic;
2710     bitVect *rsave;
2711     sym_link *dtype;
2712
2713     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2714     /* look for call */
2715     for (ic = lic ; ic ; ic = ic->next) 
2716         if (ic->op == CALL || ic->op == PCALL)
2717             break;
2718
2719     if (!ic) {
2720         fprintf(stderr,"found parameter push with no function call\n");
2721         return ;
2722     }
2723
2724     /* if the registers have been saved already then
2725     do nothing */
2726     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2727         return ;
2728
2729     /* find the registers in use at this time 
2730     and push them away to safety */
2731     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2732                           ic->rUsed);
2733
2734     ic->regsSaved = 1;
2735     if (options.useXstack) {
2736         if (bitVectBitValue(rsave,R0_IDX))
2737             pic16_emitcode("mov","b,r0");
2738         pic16_emitcode("mov","r0,%s",spname);
2739         for (i = 0 ; i < pic16_nRegs ; i++) {
2740             if (bitVectBitValue(rsave,i)) {
2741                 if (i == R0_IDX)
2742                     pic16_emitcode("mov","a,b");
2743                 else
2744                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2745                 pic16_emitcode("movx","@r0,a");
2746                 pic16_emitcode("inc","r0");
2747             }
2748         }
2749         pic16_emitcode("mov","%s,r0",spname);
2750         if (bitVectBitValue(rsave,R0_IDX))
2751             pic16_emitcode("mov","r0,b");           
2752     }// else
2753     //for (i = 0 ; i < pic16_nRegs ; i++) {
2754     //    if (bitVectBitValue(rsave,i))
2755     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2756     //}
2757
2758     dtype = operandType(IC_LEFT(ic));
2759     if (currFunc && dtype && 
2760         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2761         IFFUNC_ISISR(currFunc->type) &&
2762         !ic->bankSaved) 
2763
2764         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2765
2766 }
2767 /*-----------------------------------------------------------------*/
2768 /* unsaveRegisters - pop the pushed registers                      */
2769 /*-----------------------------------------------------------------*/
2770 static void unsaveRegisters (iCode *ic)
2771 {
2772     int i;
2773     bitVect *rsave;
2774
2775     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2776     /* find the registers in use at this time 
2777     and push them away to safety */
2778     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2779                           ic->rUsed);
2780     
2781     if (options.useXstack) {
2782         pic16_emitcode("mov","r0,%s",spname);   
2783         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2784             if (bitVectBitValue(rsave,i)) {
2785                 pic16_emitcode("dec","r0");
2786                 pic16_emitcode("movx","a,@r0");
2787                 if (i == R0_IDX)
2788                     pic16_emitcode("mov","b,a");
2789                 else
2790                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2791             }       
2792
2793         }
2794         pic16_emitcode("mov","%s,r0",spname);
2795         if (bitVectBitValue(rsave,R0_IDX))
2796             pic16_emitcode("mov","r0,b");
2797     } //else
2798     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2799     //    if (bitVectBitValue(rsave,i))
2800     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2801     //}
2802
2803 }  
2804 #endif
2805
2806 #if 0  // patch 14
2807 /*-----------------------------------------------------------------*/
2808 /* pushSide -                                                      */
2809 /*-----------------------------------------------------------------*/
2810 static void pushSide(operand * oper, int size)
2811 {
2812         int offset = 0;
2813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2814         while (size--) {
2815                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2816                 if (AOP_TYPE(oper) != AOP_REG &&
2817                     AOP_TYPE(oper) != AOP_DIR &&
2818                     strcmp(l,"a") ) {
2819                         pic16_emitcode("mov","a,%s",l);
2820                         pic16_emitcode("push","acc");
2821                 } else
2822                         pic16_emitcode("push","%s",l);
2823         }
2824 }
2825 #endif // patch 14
2826
2827 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2828 {
2829   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2830     pic16_emitpcode(POC_MOVFW, src);
2831     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2832   } else {
2833     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2834         src, pic16_popGet(AOP(op), offset)));
2835   }
2836 }
2837
2838
2839 /*-----------------------------------------------------------------*/
2840 /* assignResultValue - assign results to oper, rescall==1 is       */
2841 /*                     called from genCall() or genPcall()         */
2842 /*-----------------------------------------------------------------*/
2843 static void assignResultValue(operand * oper, int rescall)
2844 {
2845   int size = AOP_SIZE(oper);
2846   int offset=0;
2847   
2848     DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2849     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2850
2851     if(rescall) {
2852       /* assign result from a call/pcall function() */
2853                 
2854       /* function results are stored in a special order,
2855        * see top of file with Function return policy, or manual */
2856
2857       if(size <= 4) {
2858         /* 8-bits, result in WREG */
2859         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2860                         
2861         if(size>1) {
2862           /* 16-bits, result in PRODL:WREG */
2863           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2864         }
2865                         
2866         if(size>2) {
2867           /* 24-bits, result in PRODH:PRODL:WREG */
2868           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2869         }
2870                         
2871         if(size>3) {
2872           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2873           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2874         }
2875       
2876       } else {
2877         /* >32-bits, result on stack, and FSR0 points to beginning.
2878          * Fix stack when done */
2879         /* FIXME FIXME */
2880 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2881         while (size--) {
2882 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2883 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2884                 
2885           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2886           GpsuedoStkPtr++;
2887         }
2888                         
2889         /* fix stack */
2890         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2891         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2892         if(STACK_MODEL_LARGE) {
2893           emitSKPNC;
2894           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2895         }
2896       }                 
2897     } else {
2898       int areg = 0;             /* matching argument register */
2899       
2900 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2901       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2902
2903
2904       /* its called from genReceive (probably) -- VR */
2905       if(!GpsuedoStkPtr && _G.useWreg) {
2906 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2907
2908         /* The last byte in the assignment is in W */
2909         if(areg <= GpsuedoStkPtr) {
2910           size--;
2911           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2912           offset++;
2913 //          debugf("receive from WREG\n", 0);
2914         }
2915       }
2916 //      GpsuedoStkPtr++;
2917       _G.stack_lat = AOP_SIZE(oper)-1;
2918
2919       while (size) {
2920         size--;
2921         GpsuedoStkPtr++;
2922         popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2923 //        debugf("receive from STACK\n", 0);
2924         offset++;
2925       }
2926     }
2927 }
2928
2929
2930 /*-----------------------------------------------------------------*/
2931 /* genIpush - generate code for pushing this gets a little complex */
2932 /*-----------------------------------------------------------------*/
2933 static void genIpush (iCode *ic)
2934 {
2935 //  int size, offset=0;
2936
2937   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2938
2939   if(ic->parmPush) {
2940     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2941
2942     /* send to stack as normal */
2943     addSet(&_G.sendSet,ic);
2944 //    addSetHead(&_G.sendSet,ic);
2945     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2946   }
2947
2948         
2949 #if 0
2950     int size, offset = 0 ;
2951     char *l;
2952
2953
2954     /* if this is not a parm push : ie. it is spill push 
2955     and spill push is always done on the local stack */
2956     if (!ic->parmPush) {
2957
2958         /* and the item is spilt then do nothing */
2959         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2960             return ;
2961
2962         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2963         size = AOP_SIZE(IC_LEFT(ic));
2964         /* push it on the stack */
2965         while(size--) {
2966             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2967             if (*l == '#') {
2968                 MOVA(l);
2969                 l = "acc";
2970             }
2971             pic16_emitcode("push","%s",l);
2972         }
2973         return ;        
2974     }
2975
2976     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2977 #endif
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* genIpop - recover the registers: can happen only for spilling   */
2982 /*-----------------------------------------------------------------*/
2983 static void genIpop (iCode *ic)
2984 {
2985   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2986 #if 0
2987     int size,offset ;
2988
2989
2990     /* if the temp was not pushed then */
2991     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2992         return ;
2993
2994     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2995     size = AOP_SIZE(IC_LEFT(ic));
2996     offset = (size-1);
2997     while (size--) 
2998         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2999                                    FALSE,TRUE));
3000
3001     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3002 #endif
3003 }
3004
3005 #if 0
3006 /*-----------------------------------------------------------------*/
3007 /* unsaverbank - restores the resgister bank from stack            */
3008 /*-----------------------------------------------------------------*/
3009 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3010 {
3011   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3012 #if 0
3013     int i;
3014     asmop *aop ;
3015     regs *r = NULL;
3016
3017     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3018     if (popPsw) {
3019         if (options.useXstack) {
3020             aop = newAsmop(0);
3021             r = getFreePtr(ic,&aop,FALSE);
3022             
3023             
3024             pic16_emitcode("mov","%s,_spx",r->name);
3025             pic16_emitcode("movx","a,@%s",r->name);
3026             pic16_emitcode("mov","psw,a");
3027             pic16_emitcode("dec","%s",r->name);
3028             
3029         }else
3030             pic16_emitcode ("pop","psw");
3031     }
3032
3033     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3034         if (options.useXstack) {       
3035             pic16_emitcode("movx","a,@%s",r->name);
3036             //pic16_emitcode("mov","(%s+%d),a",
3037             //       regspic16[i].base,8*bank+regspic16[i].offset);
3038             pic16_emitcode("dec","%s",r->name);
3039
3040         } else 
3041           pic16_emitcode("pop",""); //"(%s+%d)",
3042         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3043     }
3044
3045     if (options.useXstack) {
3046
3047         pic16_emitcode("mov","_spx,%s",r->name);
3048         pic16_freeAsmop(NULL,aop,ic,TRUE);
3049
3050     }
3051 #endif 
3052 }
3053
3054 /*-----------------------------------------------------------------*/
3055 /* saverbank - saves an entire register bank on the stack          */
3056 /*-----------------------------------------------------------------*/
3057 static void saverbank (int bank, iCode *ic, bool pushPsw)
3058 {
3059   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3060 #if 0
3061     int i;
3062     asmop *aop ;
3063     regs *r = NULL;
3064
3065     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3066     if (options.useXstack) {
3067
3068         aop = newAsmop(0);
3069         r = getFreePtr(ic,&aop,FALSE);  
3070         pic16_emitcode("mov","%s,_spx",r->name);
3071
3072     }
3073
3074     for (i = 0 ; i < pic16_nRegs ;i++) {
3075         if (options.useXstack) {
3076             pic16_emitcode("inc","%s",r->name);
3077             //pic16_emitcode("mov","a,(%s+%d)",
3078             //         regspic16[i].base,8*bank+regspic16[i].offset);
3079             pic16_emitcode("movx","@%s,a",r->name);           
3080         } else 
3081           pic16_emitcode("push","");// "(%s+%d)",
3082                      //regspic16[i].base,8*bank+regspic16[i].offset);
3083     }
3084     
3085     if (pushPsw) {
3086         if (options.useXstack) {
3087             pic16_emitcode("mov","a,psw");
3088             pic16_emitcode("movx","@%s,a",r->name);     
3089             pic16_emitcode("inc","%s",r->name);
3090             pic16_emitcode("mov","_spx,%s",r->name);       
3091             pic16_freeAsmop (NULL,aop,ic,TRUE);
3092             
3093         } else
3094             pic16_emitcode("push","psw");
3095         
3096         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3097     }
3098     ic->bankSaved = 1;
3099 #endif
3100 }
3101 #endif  /* 0 */
3102
3103
3104 static int wparamCmp(void *p1, void *p2)
3105 {
3106   return (!strcmp((char *)p1, (char *)p2));
3107 }
3108
3109 int inWparamList(char *s)
3110 {
3111   return isinSetWith(wparamList, s, wparamCmp);
3112
3113
3114
3115 /*-----------------------------------------------------------------*/
3116 /* genCall - generates a call statement                            */
3117 /*-----------------------------------------------------------------*/
3118 static void genCall (iCode *ic)
3119 {
3120   sym_link *ftype;   
3121   int stackParms=0;
3122   int use_wreg=0;
3123   int inwparam=0;
3124   char *fname;
3125   
3126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3127
3128     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3129     /* if caller saves & we have not saved then */
3130 //    if (!ic->regsSaved)
3131 //      saveRegisters(ic);
3132
3133         /* initialise stackParms for IPUSH pushes */
3134 //      stackParms = psuedoStkPtr;
3135 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3136     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3137     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3138
3139 #if 0
3140     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3141 #endif
3142
3143     /* if send set is not empty the assign */
3144     if (_G.sendSet) {
3145       iCode *sic;
3146       int psuedoStkPtr=-1; 
3147       int firstTimeThruLoop = 1;
3148
3149
3150         /* reverse sendSet if function is not reentrant */
3151         if(!IFFUNC_ISREENT(ftype))
3152           _G.sendSet = reverseSet(_G.sendSet);
3153
3154         /* First figure how many parameters are getting passed */
3155         stackParms = 0;
3156         use_wreg = 0;
3157         
3158         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3159           int size;
3160 //          int offset = 0;
3161
3162             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3163             size = AOP_SIZE(IC_LEFT(sic));
3164
3165             stackParms += size;
3166
3167             /* pass the last byte through WREG */
3168             if(inwparam) {
3169
3170               while (size--) {
3171                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3172                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3173                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3174
3175                 if(!firstTimeThruLoop) {
3176                   /* If this is not the first time we've been through the loop
3177                    * then we need to save the parameter in a temporary
3178                    * register. The last byte of the last parameter is
3179                    * passed in W. */
3180
3181                   pushw();
3182 //                  --psuedoStkPtr;             // sanity check
3183                   use_wreg = 1;
3184                 }
3185                 
3186                 firstTimeThruLoop=0;
3187
3188                 mov2w (AOP(IC_LEFT(sic)), size);
3189
3190 //                offset++;
3191               }
3192             } else {
3193               /* all arguments are passed via stack */
3194               use_wreg = 0;
3195
3196               while (size--) {
3197                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3198                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3199                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3200
3201 //                pushaop(AOP(IC_LEFT(sic)), size);
3202                 mov2w (AOP(IC_LEFT(sic)), size);
3203                 pushw();
3204               }
3205             }
3206
3207             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3208           }
3209
3210           if(inwparam) {
3211             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3212               pushw();  /* save last parameter to stack if functions has varargs */
3213               use_wreg = 0;
3214             } else
3215               use_wreg = 1;
3216           } else use_wreg = 0;
3217
3218           _G.stackRegSet = _G.sendSet;
3219           _G.sendSet = NULL;
3220     }
3221
3222     /* make the call */
3223     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3224
3225     GpsuedoStkPtr=0;
3226     
3227     /* if we need to assign a result value */
3228     if ((IS_ITEMP(IC_RESULT(ic))
3229           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3230               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3231         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3232
3233       _G.accInUse++;
3234       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3235       _G.accInUse--;
3236
3237       assignResultValue(IC_RESULT(ic), 1);
3238
3239       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3240                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3241                 
3242       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3243     }
3244
3245     if(!stackParms && ic->parmBytes) {
3246       stackParms = ic->parmBytes;
3247     }
3248       
3249     stackParms -= use_wreg;
3250     
3251     if(stackParms>0) {
3252       if(stackParms == 1) {
3253         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3254       } else {
3255         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3256         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3257       }
3258       if(STACK_MODEL_LARGE) {
3259         emitSKPNC;
3260         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3261       }
3262     }
3263
3264 #if 0
3265     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3266 #endif
3267
3268     /* adjust the stack for parameters if required */
3269 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3270
3271 #if 0
3272       /* if register bank was saved then pop them */
3273       if (ic->bankSaved)
3274         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3275
3276       /* if we hade saved some registers then unsave them */
3277       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3278         unsaveRegisters (ic);
3279 #endif
3280 }
3281
3282
3283
3284 /*-----------------------------------------------------------------*/
3285 /* genPcall - generates a call by pointer statement                */
3286 /*            new version, created from genCall - HJD              */
3287 /*-----------------------------------------------------------------*/
3288 static void genPcall (iCode *ic)
3289 {
3290   sym_link *ftype, *fntype;
3291   int stackParms=0;
3292   symbol *retlbl = newiTempLabel(NULL);
3293   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3294   
3295     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3296
3297     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3298     fntype = operandType( IC_LEFT(ic) )->next;
3299
3300     /* if send set is not empty the assign */
3301     if (_G.sendSet) {
3302       iCode *sic;
3303       int psuedoStkPtr=-1; 
3304
3305       /* reverse sendSet if function is not reentrant */
3306       if(!IFFUNC_ISREENT(fntype))
3307         _G.sendSet = reverseSet(_G.sendSet);
3308
3309       stackParms = 0;
3310       
3311       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3312         int size;
3313
3314           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3315           size = AOP_SIZE(IC_LEFT(sic));
3316           stackParms += size;
3317
3318           /* all parameters are passed via stack, since WREG is clobbered
3319            * by the calling sequence */
3320           while (size--) {
3321             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3322             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3323             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3324
3325             mov2w (AOP(IC_LEFT(sic)), size);
3326             pushw();
3327           }
3328
3329           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3330       }
3331
3332       _G.stackRegSet = _G.sendSet;
3333       _G.sendSet = NULL;
3334     }
3335
3336     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3337
3338     // push return address
3339     // push $ on return stack, then replace with retlbl
3340
3341     pic16_emitpcodeNULLop(POC_PUSH);
3342
3343     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3344     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3345     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3346     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3347     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3348     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3349
3350     /* make the call by writing the pointer into pc */
3351     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3352     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3353
3354     // note: MOVFF to PCL not allowed
3355     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3356     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3357
3358
3359     /* return address is here: (X) */
3360     pic16_emitpLabelFORCE(retlbl->key);
3361
3362     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3363
3364     GpsuedoStkPtr=0;
3365     /* if we need assign a result value */
3366     if ((IS_ITEMP(IC_RESULT(ic))
3367           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3368               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3369         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3370
3371       _G.accInUse++;
3372       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3373       _G.accInUse--;
3374
3375       assignResultValue(IC_RESULT(ic), 1);
3376
3377       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3378               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3379                 
3380       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3381     }
3382
3383 //    stackParms -= use_wreg;
3384     
3385     if(stackParms>0) {
3386       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3387       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3388       if(STACK_MODEL_LARGE) {
3389         /* this implies that stackParms < 256 !!! -- VR */
3390         emitSKPNC;
3391         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3392       }
3393     }
3394 }
3395
3396 /*-----------------------------------------------------------------*/
3397 /* resultRemat - result  is rematerializable                       */
3398 /*-----------------------------------------------------------------*/
3399 static int resultRemat (iCode *ic)
3400 {
3401   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3402   if (SKIP_IC(ic) || ic->op == IFX)
3403     return 0;
3404
3405   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3406     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3407     if (sym->remat && !POINTER_SET(ic)) 
3408       return 1;
3409   }
3410
3411   return 0;
3412 }
3413
3414 #if defined(__BORLANDC__) || defined(_MSC_VER)
3415 #define STRCASECMP stricmp
3416 #else
3417 #define STRCASECMP strcasecmp
3418 #endif
3419
3420 #if 0
3421 /*-----------------------------------------------------------------*/
3422 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3423 /*-----------------------------------------------------------------*/
3424 static bool inExcludeList(char *s)
3425 {
3426   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3427     int i =0;
3428     
3429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3430     if (options.excludeRegs[i] &&
3431     STRCASECMP(options.excludeRegs[i],"none") == 0)
3432         return FALSE ;
3433
3434     for ( i = 0 ; options.excludeRegs[i]; i++) {
3435         if (options.excludeRegs[i] &&
3436         STRCASECMP(s,options.excludeRegs[i]) == 0)
3437             return TRUE;
3438     }
3439     return FALSE ;
3440 }
3441 #endif
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genFunction - generated code for function entry                 */
3445 /*-----------------------------------------------------------------*/
3446 static void genFunction (iCode *ic)
3447 {
3448   symbol *sym;
3449   sym_link *ftype;
3450   
3451     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3452
3453     pic16_labelOffset += (max_key+4);
3454     max_key=0;
3455     GpsuedoStkPtr=0;
3456     _G.nRegsSaved = 0;
3457         
3458     ftype = operandType(IC_LEFT(ic));
3459     sym = OP_SYMBOL(IC_LEFT(ic));
3460
3461     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3462       /* create an absolute section at the interrupt vector:
3463        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3464       symbol *asym;
3465       char asymname[128];
3466       pBlock *apb;
3467
3468         {
3469           int i, found=-1;
3470
3471             sym = OP_SYMBOL( IC_LEFT(ic));
3472             for(i=0;i<=2;i++) {
3473               if(interrupts[i]->name
3474                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3475                   found = i;
3476                   break;
3477               }
3478             }
3479                         
3480             if(found == -1) {
3481               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3482                             __FILE__, __LINE__, sym->name);
3483               assert( 0 );
3484             }
3485             _G.interruptvector = found;
3486         }
3487
3488         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3489         asym = newSymbol(asymname, 0);
3490
3491         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3492         pic16_addpBlock( apb );
3493
3494         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3495         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3496         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3497                 
3498         /* mark the end of this tiny function */
3499         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3500
3501         {
3502           absSym *abSym;
3503
3504             abSym = Safe_calloc(1, sizeof(absSym));
3505             strcpy(abSym->name, asymname);
3506
3507             switch( _G.interruptvector ) {
3508               case 0: abSym->address = 0x000000; break;
3509               case 1: abSym->address = 0x000008; break;
3510               case 2: abSym->address = 0x000018; break;
3511             }
3512
3513             /* relocate interrupt vectors if needed */
3514             abSym->address += pic16_options.ivt_loc;
3515
3516             addSet(&absSymSet, abSym);
3517         }
3518     }
3519
3520     /* create the function header */
3521     pic16_emitcode(";","-----------------------------------------");
3522     pic16_emitcode(";"," function %s",sym->name);
3523     pic16_emitcode(";","-----------------------------------------");
3524
3525     pic16_emitcode("","%s:",sym->rname);
3526     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3527
3528
3529     {
3530       absSym *ab;
3531
3532         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3533           if(!strcmp(ab->name, sym->rname)) {
3534             pic16_pBlockConvert2Absolute(pb);
3535             break;
3536           }
3537         }
3538     }
3539
3540
3541     if(IFFUNC_ISNAKED(ftype)) {
3542       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3543       return;
3544     }
3545         
3546     /* if critical function then turn interrupts off */
3547     if (IFFUNC_ISCRITICAL(ftype)) {
3548       //pic16_emitcode("clr","ea");
3549     }
3550
3551     _G.fregsUsed = sym->regsUsed;
3552
3553     /* if this is an interrupt service routine then
3554      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3555     if (IFFUNC_ISISR(sym->type)) {
3556         _G.usefastretfie = 1;   /* use shadow registers by default */
3557         
3558         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3559         if(!(_G.interruptvector == 1)) {
3560           /* do not save WREG,STATUS,BSR for high priority interrupts
3561            * because they are stored in the hardware shadow registers already */
3562           _G.usefastretfie = 0;
3563           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3564           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3565           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3566         }
3567
3568         /* these should really be optimized somehow, because not all
3569          * interrupt handlers modify them */
3570         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3571         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3572         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3573         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3574         
3575 //        pic16_pBlockConvert2ISR(pb);
3576                 
3577     }
3578
3579     /* emit code to setup stack frame if user enabled,
3580      * and function is not main() */
3581          
3582     //fprintf(stderr, "function name: %s\n", sym->name);
3583     if(strcmp(sym->name, "main")) {
3584       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3585         /* setup the stack frame */
3586         if(STACK_MODEL_LARGE)
3587           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3588         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3589 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3590         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3591         if(STACK_MODEL_LARGE)
3592           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3593       }
3594     }
3595
3596     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3597           && sym->stack) {
3598
3599       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3600
3601       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3602       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3603       emitSKPNC;
3604       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3605     }
3606           
3607     if(inWparamList(sym->name)) {
3608       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3609         _G.useWreg = 0;
3610       else
3611         _G.useWreg = 1;
3612     } else
3613       _G.useWreg = 0;
3614
3615     /* if callee-save to be used for this function
3616      * then save the registers being used in this function */
3617 //    if (IFFUNC_CALLEESAVES(sym->type))
3618     {
3619       int i;
3620
3621         /* if any registers used */
3622         if (sym->regsUsed) {
3623           /* save the registers used */
3624           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3625           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3626           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3627             if (bitVectBitValue(sym->regsUsed,i)) {
3628               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3629               _G.nRegsSaved++;
3630
3631               if(!pic16_regWithIdx(i)->wasUsed) {
3632                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3633                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3634                 pic16_regWithIdx(i)->wasUsed = 1;
3635               }
3636             }
3637           }
3638           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3639         }
3640     }
3641         
3642     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3643 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genEndFunction - generates epilogue for functions               */
3648 /*-----------------------------------------------------------------*/
3649 static void genEndFunction (iCode *ic)
3650 {
3651   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3652
3653     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3654
3655     if(IFFUNC_ISNAKED(sym->type)) {
3656       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3657       return;
3658     }
3659
3660     _G.stack_lat = 0;
3661
3662     /* add code for ISCRITICAL */
3663     if(IFFUNC_ISCRITICAL(sym->type)) {
3664       /* if critical function, turn on interrupts */
3665       
3666       /* TODO: add code here -- VR */
3667     }
3668     
3669     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3670           && sym->stack) {
3671       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3672       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3673       emitSKPNC;
3674       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3675     }
3676
3677 //    sym->regsUsed = _G.fregsUsed;
3678     
3679     /* now we need to restore the registers */
3680     /* if any registers used */
3681     if (sym->regsUsed) {
3682       int i;
3683
3684         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3685         /* restore registers used */
3686         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3687         for ( i = sym->regsUsed->size; i >= 0; i--) {
3688           if (bitVectBitValue(sym->regsUsed,i)) {
3689             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3690             _G.nRegsSaved--;
3691           }
3692         }
3693         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3694
3695     }
3696
3697     if(strcmp(sym->name, "main")) {
3698       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3699         /* restore stack frame */
3700         if(STACK_MODEL_LARGE)
3701           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3702 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3703         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3704 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3705       }
3706     }
3707
3708     _G.useWreg = 0;
3709
3710     if (IFFUNC_ISISR(sym->type)) {
3711       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3712       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3713       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3714       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3715
3716       if(!(_G.interruptvector == 1)) {
3717         /* do not restore interrupt vector for WREG,STATUS,BSR
3718          * for high priority interrupt, see genFunction */
3719         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3720         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3721         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3722       }
3723       _G.interruptvector = 0;           /* sanity check */
3724
3725
3726       /* if debug then send end of function */
3727 /*      if (options.debug && currFunc)  */
3728       if (currFunc) {
3729         debugFile->writeEndFunction (currFunc, ic, 1);
3730       }
3731         
3732       if(_G.usefastretfie)
3733         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3734       else
3735         pic16_emitpcodeNULLop(POC_RETFIE);
3736
3737       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3738       
3739       _G.usefastretfie = 0;
3740       return;
3741     }
3742
3743     if (IFFUNC_ISCRITICAL(sym->type)) {
3744       pic16_emitcode("setb","ea");
3745     }
3746
3747     /* if debug then send end of function */
3748     if (currFunc) {
3749       debugFile->writeEndFunction (currFunc, ic, 1);
3750     }
3751
3752     /* insert code to restore stack frame, if user enabled it
3753      * and function is not main() */
3754          
3755
3756     pic16_emitpcodeNULLop(POC_RETURN);
3757
3758     /* Mark the end of a function */
3759     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3760 }
3761
3762
3763 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3764 {
3765   if(is_LitOp(op)) {
3766     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3767       if(lit == 0) {
3768         pic16_emitpcode(POC_CLRF, dest);
3769       } else {
3770         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3771         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3772       }
3773   } else {
3774     if(dest->type == PO_WREG && (offset == 0)) {
3775       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3776       return;
3777     }
3778     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3779   }
3780 }
3781
3782 /*-----------------------------------------------------------------*/
3783 /* genRet - generate code for return statement                     */
3784 /*-----------------------------------------------------------------*/
3785 static void genRet (iCode *ic)
3786 {
3787   int size;
3788   operand *left;
3789
3790         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3791         /* if we have no return value then
3792          * just generate the "ret" */
3793         
3794         if (!IC_LEFT(ic)) 
3795                 goto jumpret;       
3796     
3797         /* we have something to return then
3798          * move the return value into place */
3799         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3800         size = AOP_SIZE(IC_LEFT(ic));
3801
3802         if(size <= 4) {
3803                 if(size>3) {
3804                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3805 //                      pic16_emitpcode(POC_MOVFF,
3806 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3807                 }
3808                 if(size>2) {
3809                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3810 //                      pic16_emitpcode(POC_MOVFF,
3811 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3812                 }
3813                 if(size>1) {
3814                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3815 //                      pic16_emitpcode(POC_MOVFF,
3816 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3817                 }
3818
3819 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3820
3821                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3822 //              pic16_emitpcode(POC_MOVFF,
3823 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3824
3825         } else {
3826                 /* >32-bits, setup stack and FSR0 */
3827                 while (size--) {
3828 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3829 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3830
3831                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3832
3833 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3834                         GpsuedoStkPtr++;
3835                 }
3836                         
3837                 /* setup FSR0 */
3838                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3839                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3840
3841                 if(STACK_MODEL_LARGE) {
3842                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3843                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3844                 } else {
3845                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3846                 }
3847         }
3848                                 
3849 #if 0
3850         /* old code, left here for reference -- VR */    
3851         while (size--) {
3852           char *l ;
3853
3854                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3855                         /* #NOCHANGE */
3856                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3857                         pic16_emitpcomment("push %s",l);
3858                         pushed++;
3859                 } else {
3860                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3861                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3862                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3863                         
3864                         if (strcmp(fReturn[offset],l)) {
3865                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3866                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3867                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3868                                 } else {
3869                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3870                                 }
3871                                 
3872                                 if(size) {
3873                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3874                                 }
3875                                 offset++;
3876                         }
3877                 }
3878         }    
3879
3880         if (pushed) {
3881                 while(pushed) {
3882                         pushed--;
3883                         if (strcmp(fReturn[pushed],"a"))
3884                                 pic16_emitcode("pop",fReturn[pushed]);
3885                         else
3886                                 pic16_emitcode("pop","acc");
3887                 }
3888         }
3889 #endif
3890
3891
3892         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3893     
3894 jumpret:
3895         /* generate a jump to the return label
3896          * if the next is not the return statement */
3897         if (!(ic->next && ic->next->op == LABEL
3898                 && IC_LABEL(ic->next) == returnLabel)) {
3899         
3900                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3901                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3902         }
3903 }
3904
3905 /*-----------------------------------------------------------------*/
3906 /* genLabel - generates a label                                    */
3907 /*-----------------------------------------------------------------*/
3908 static void genLabel (iCode *ic)
3909 {
3910
3911
3912     /* special case never generate */
3913     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3914     if (IC_LABEL(ic) == entryLabel)
3915         return ;
3916
3917     pic16_emitpLabel(IC_LABEL(ic)->key);
3918     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3919 }
3920
3921 /*-----------------------------------------------------------------*/
3922 /* genGoto - generates a goto                                      */
3923 /*-----------------------------------------------------------------*/
3924 //tsd
3925 static void genGoto (iCode *ic)
3926 {
3927   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3928   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3929 }
3930
3931
3932 /*-----------------------------------------------------------------*/
3933 /* genMultbits :- multiplication of bits                           */
3934 /*-----------------------------------------------------------------*/
3935 static void genMultbits (operand *left, 
3936                          operand *right, 
3937                          operand *result)
3938 {
3939   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3940
3941   if(!pic16_sameRegs(AOP(result),AOP(right)))
3942     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3943
3944   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3945   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3946   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3947
3948 }
3949
3950
3951 /*-----------------------------------------------------------------*/
3952 /* genMultOneByte : 8 bit multiplication & division                */
3953 /*-----------------------------------------------------------------*/
3954 static void genMultOneByte (operand *left,
3955                             operand *right,
3956                             operand *result)
3957 {
3958
3959   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3960   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3961   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3962
3963   /* (if two literals, the value is computed before) */
3964   /* if one literal, literal on the right */
3965   if (AOP_TYPE(left) == AOP_LIT){
3966     operand *t = right;
3967     right = left;
3968     left = t;
3969   }
3970
3971         /* size is already checked in genMult == 1 */
3972 //      size = AOP_SIZE(result);
3973
3974         if (AOP_TYPE(right) == AOP_LIT){
3975                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3976                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3977                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3978                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3979         } else {
3980                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3981                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3982                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3983                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3984         }
3985         
3986         pic16_genMult8X8_8 (left, right,result);
3987 }
3988
3989 /*-----------------------------------------------------------------*/
3990 /* genMultOneWord : 16 bit multiplication                          */
3991 /*-----------------------------------------------------------------*/
3992 static void genMultOneWord (operand *left,
3993                             operand *right,
3994                             operand *result)
3995 {
3996
3997         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3998         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3999         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4000
4001         /* (if two literals, the value is computed before)
4002          * if one literal, literal on the right */
4003         if (AOP_TYPE(left) == AOP_LIT){
4004           operand *t = right;
4005                 right = left;
4006                 left = t;
4007         }
4008
4009         /* size is checked already == 2 */
4010 //      size = AOP_SIZE(result);
4011
4012         if (AOP_TYPE(right) == AOP_LIT) {
4013                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4014                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4015                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4016                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4017         } else {
4018                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4019                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4020                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4021                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4022         }
4023         
4024         pic16_genMult16X16_16(left, right,result);
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genMultOneLong : 32 bit multiplication                          */
4029 /*-----------------------------------------------------------------*/
4030 static void genMultOneLong (operand *left,
4031                             operand *right,
4032                             operand *result)
4033 {
4034
4035         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4036         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4037         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4038
4039         /* (if two literals, the value is computed before)
4040          * if one literal, literal on the right */
4041         if (AOP_TYPE(left) == AOP_LIT){
4042           operand *t = right;
4043                 right = left;
4044                 left = t;
4045         }
4046
4047         /* size is checked already == 4 */
4048 //      size = AOP_SIZE(result);
4049
4050         if (AOP_TYPE(right) == AOP_LIT) {
4051                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4052                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4053                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4054                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4055         } else {
4056                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4057                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4058                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4059                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4060         }
4061         
4062         pic16_genMult32X32_32(left, right,result);
4063 }
4064
4065
4066
4067 /*-----------------------------------------------------------------*/
4068 /* genMult - generates code for multiplication                     */
4069 /*-----------------------------------------------------------------*/
4070 static void genMult (iCode *ic)
4071 {
4072   operand *left = IC_LEFT(ic);
4073   operand *right = IC_RIGHT(ic);
4074   operand *result= IC_RESULT(ic);   
4075
4076         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4077         /* assign the amsops */
4078         pic16_aopOp (left,ic,FALSE);
4079         pic16_aopOp (right,ic,FALSE);
4080         pic16_aopOp (result,ic,TRUE);
4081
4082         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4083
4084         /* special cases first *
4085         * both are bits */
4086         if (AOP_TYPE(left) == AOP_CRY
4087                 && AOP_TYPE(right)== AOP_CRY) {
4088                 genMultbits(left,right,result);
4089           goto release ;
4090         }
4091
4092         /* if both are of size == 1 */
4093         if(AOP_SIZE(left) == 1
4094                 && AOP_SIZE(right) == 1) {
4095                 genMultOneByte(left,right,result);
4096           goto release ;
4097         }
4098
4099         /* if both are of size == 2 */
4100         if(AOP_SIZE(left) == 2
4101                 && AOP_SIZE(right) == 2) {
4102                 genMultOneWord(left, right, result);
4103           goto release;
4104         }
4105         
4106         /* if both are of size == 4 */
4107         if(AOP_SIZE(left) == 4
4108                 && AOP_SIZE(right) == 4) {
4109                 genMultOneLong(left, right, result);
4110           goto release;
4111         }
4112         
4113         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4114
4115
4116         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4117         /* should have been converted to function call */
4118         assert(0) ;
4119
4120 release :
4121         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4122         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4123         pic16_freeAsmop(result,NULL,ic,TRUE); 
4124 }
4125
4126 /*-----------------------------------------------------------------*/
4127 /* genDivbits :- division of bits                                  */
4128 /*-----------------------------------------------------------------*/
4129 static void genDivbits (operand *left, 
4130                         operand *right, 
4131                         operand *result)
4132 {
4133
4134     char *l;
4135
4136     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4137     /* the result must be bit */    
4138     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4139     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4140
4141     MOVA(l);    
4142
4143     pic16_emitcode("div","ab");
4144     pic16_emitcode("rrc","a");
4145     pic16_aopPut(AOP(result),"c",0);
4146 }
4147
4148 /*-----------------------------------------------------------------*/
4149 /* genDivOneByte : 8 bit division                                  */
4150 /*-----------------------------------------------------------------*/
4151 static void genDivOneByte (operand *left,
4152                            operand *right,
4153                            operand *result)
4154 {
4155     sym_link *opetype = operandType(result);
4156     char *l ;
4157     symbol *lbl ;
4158     int size,offset;
4159
4160         /* result = divident / divisor
4161          * - divident may be a register or a literal,
4162          * - divisor may be a register or a literal,
4163          * so there are 3 cases (literal / literal is optimized
4164          * by the front-end) to handle.
4165          * In addition we must handle signed and unsigned, which
4166          * result in 6 final different cases -- VR */
4167
4168     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4169     size = AOP_SIZE(result) - 1;
4170     offset = 1;
4171     /* signed or unsigned */
4172     if (SPEC_USIGN(opetype)) {
4173       pCodeOp *pct1,    /* count */
4174                 *pct2,  /* reste */
4175                 *pct3;  /* temp */
4176       symbol *label1, *label2, *label3;;
4177
4178
4179         /* unsigned is easy */
4180
4181         pct1 = pic16_popGetTempReg(1);
4182         pct2 = pic16_popGetTempReg(1);
4183         pct3 = pic16_popGetTempReg(1);
4184         
4185         label1 = newiTempLabel(NULL);
4186         label2 = newiTempLabel(NULL);
4187         label3 = newiTempLabel(NULL);
4188
4189         /* the following algorithm is extracted from divuint.c */
4190
4191         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4192         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4193         
4194         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4195
4196         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4197         
4198         pic16_emitpLabel(label1->key);
4199         
4200         emitCLRC;
4201         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4202
4203
4204         emitCLRC;
4205         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4206         
4207
4208         emitSKPNC;
4209         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4210         
4211         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4212         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4213         
4214         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4215         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4216         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4217         
4218         pic16_emitpLabel( label3->key );
4219         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4220         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4221         
4222         
4223
4224         pic16_emitpLabel(label2->key);
4225         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4226         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4227         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4228         
4229         /* result is in wreg */
4230         if(AOP_TYPE(result) != AOP_ACC)
4231                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4232
4233         pic16_popReleaseTempReg( pct3, 1);
4234         pic16_popReleaseTempReg( pct2, 1);
4235         pic16_popReleaseTempReg( pct1, 1);
4236
4237         return ;
4238     }
4239
4240     /* signed is a little bit more difficult */
4241
4242     /* save the signs of the operands */
4243     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4244     MOVA(l);    
4245     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4246     pic16_emitcode("push","acc"); /* save it on the stack */
4247
4248     /* now sign adjust for both left & right */
4249     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4250     MOVA(l);       
4251     lbl = newiTempLabel(NULL);
4252     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4253     pic16_emitcode("cpl","a");   
4254     pic16_emitcode("inc","a");
4255     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4256     pic16_emitcode("mov","b,a");
4257
4258     /* sign adjust left side */
4259     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4260     MOVA(l);
4261
4262     lbl = newiTempLabel(NULL);
4263     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4264     pic16_emitcode("cpl","a");
4265     pic16_emitcode("inc","a");
4266     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4267
4268     /* now the division */
4269     pic16_emitcode("div","ab");
4270     /* we are interested in the lower order
4271     only */
4272     pic16_emitcode("mov","b,a");
4273     lbl = newiTempLabel(NULL);
4274     pic16_emitcode("pop","acc");   
4275     /* if there was an over flow we don't 
4276     adjust the sign of the result */
4277     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4278     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4279     CLRC;
4280     pic16_emitcode("clr","a");
4281     pic16_emitcode("subb","a,b");
4282     pic16_emitcode("mov","b,a");
4283     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4284
4285     /* now we are done */
4286     pic16_aopPut(AOP(result),"b",0);
4287     if(size > 0){
4288         pic16_emitcode("mov","c,b.7");
4289         pic16_emitcode("subb","a,acc");   
4290     }
4291     while (size--)
4292         pic16_aopPut(AOP(result),"a",offset++);
4293
4294 }
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genDiv - generates code for division                            */
4298 /*-----------------------------------------------------------------*/
4299 static void genDiv (iCode *ic)
4300 {
4301     operand *left = IC_LEFT(ic);
4302     operand *right = IC_RIGHT(ic);
4303     operand *result= IC_RESULT(ic);   
4304
4305
4306         /* Division is a very lengthy algorithm, so it is better
4307          * to call support routines than inlining algorithm.
4308          * Division functions written here just in case someone
4309          * wants to inline and not use the support libraries -- VR */
4310
4311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4312     /* assign the amsops */
4313     pic16_aopOp (left,ic,FALSE);
4314     pic16_aopOp (right,ic,FALSE);
4315     pic16_aopOp (result,ic,TRUE);
4316
4317     /* special cases first */
4318     /* both are bits */
4319     if (AOP_TYPE(left) == AOP_CRY &&
4320         AOP_TYPE(right)== AOP_CRY) {
4321         genDivbits(left,right,result);
4322         goto release ;
4323     }
4324
4325     /* if both are of size == 1 */
4326     if (AOP_SIZE(left) == 1 &&
4327         AOP_SIZE(right) == 1 ) {
4328         genDivOneByte(left,right,result);
4329         goto release ;
4330     }
4331
4332     /* should have been converted to function call */
4333     assert(0);
4334 release :
4335     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4336     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4337     pic16_freeAsmop(result,NULL,ic,TRUE); 
4338 }
4339
4340 /*-----------------------------------------------------------------*/
4341 /* genModbits :- modulus of bits                                   */
4342 /*-----------------------------------------------------------------*/
4343 static void genModbits (operand *left, 
4344                         operand *right, 
4345                         operand *result)
4346 {
4347
4348     char *l;
4349
4350     /* the result must be bit */    
4351     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4352     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4353
4354     MOVA(l);       
4355
4356     pic16_emitcode("div","ab");
4357     pic16_emitcode("mov","a,b");
4358     pic16_emitcode("rrc","a");
4359     pic16_aopPut(AOP(result),"c",0);
4360 }
4361
4362 /*-----------------------------------------------------------------*/
4363 /* genModOneByte : 8 bit modulus                                   */
4364 /*-----------------------------------------------------------------*/
4365 static void genModOneByte (operand *left,
4366                            operand *right,
4367                            operand *result)
4368 {
4369     sym_link *opetype = operandType(result);
4370     char *l ;
4371     symbol *lbl ;
4372
4373     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4374     /* signed or unsigned */
4375     if (SPEC_USIGN(opetype)) {
4376         /* unsigned is easy */
4377         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4378         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4379         MOVA(l);    
4380         pic16_emitcode("div","ab");
4381         pic16_aopPut(AOP(result),"b",0);
4382         return ;
4383     }
4384
4385     /* signed is a little bit more difficult */
4386
4387     /* save the signs of the operands */
4388     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4389     MOVA(l);
4390
4391     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4392     pic16_emitcode("push","acc"); /* save it on the stack */
4393
4394     /* now sign adjust for both left & right */
4395     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4396     MOVA(l);
4397
4398     lbl = newiTempLabel(NULL);
4399     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4400     pic16_emitcode("cpl","a");   
4401     pic16_emitcode("inc","a");
4402     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4403     pic16_emitcode("mov","b,a"); 
4404
4405     /* sign adjust left side */
4406     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4407     MOVA(l);
4408
4409     lbl = newiTempLabel(NULL);
4410     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4411     pic16_emitcode("cpl","a");   
4412     pic16_emitcode("inc","a");
4413     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4414
4415     /* now the multiplication */
4416     pic16_emitcode("div","ab");
4417     /* we are interested in the lower order
4418     only */
4419     lbl = newiTempLabel(NULL);
4420     pic16_emitcode("pop","acc");   
4421     /* if there was an over flow we don't 
4422     adjust the sign of the result */
4423     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4424     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4425     CLRC ;
4426     pic16_emitcode("clr","a");
4427     pic16_emitcode("subb","a,b");
4428     pic16_emitcode("mov","b,a");
4429     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4430
4431     /* now we are done */
4432     pic16_aopPut(AOP(result),"b",0);
4433
4434 }
4435
4436 /*-----------------------------------------------------------------*/
4437 /* genMod - generates code for division                            */
4438 /*-----------------------------------------------------------------*/
4439 static void genMod (iCode *ic)
4440 {
4441     operand *left = IC_LEFT(ic);
4442     operand *right = IC_RIGHT(ic);
4443     operand *result= IC_RESULT(ic);  
4444
4445     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4446     /* assign the amsops */
4447     pic16_aopOp (left,ic,FALSE);
4448     pic16_aopOp (right,ic,FALSE);
4449     pic16_aopOp (result,ic,TRUE);
4450
4451     /* special cases first */
4452     /* both are bits */
4453     if (AOP_TYPE(left) == AOP_CRY &&
4454         AOP_TYPE(right)== AOP_CRY) {
4455         genModbits(left,right,result);
4456         goto release ;
4457     }
4458
4459     /* if both are of size == 1 */
4460     if (AOP_SIZE(left) == 1 &&
4461         AOP_SIZE(right) == 1 ) {
4462         genModOneByte(left,right,result);
4463         goto release ;
4464     }
4465
4466     /* should have been converted to function call */
4467     assert(0);
4468
4469 release :
4470     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4471     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4472     pic16_freeAsmop(result,NULL,ic,TRUE); 
4473 }
4474
4475 /*-----------------------------------------------------------------*/
4476 /* genIfxJump :- will create a jump depending on the ifx           */
4477 /*-----------------------------------------------------------------*/
4478 /*
4479   note: May need to add parameter to indicate when a variable is in bit space.
4480 */
4481 static void genIfxJump (iCode *ic, char *jval)
4482 {
4483
4484     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4485     /* if true label then we jump if condition
4486     supplied is true */
4487     if ( IC_TRUE(ic) ) {
4488
4489         if(strcmp(jval,"a") == 0)
4490           emitSKPZ;
4491         else if (strcmp(jval,"c") == 0)
4492           emitSKPC;
4493         else {
4494           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4495           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4496         }
4497
4498         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4499         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4500
4501     }
4502     else {
4503         /* false label is present */
4504         if(strcmp(jval,"a") == 0)
4505           emitSKPNZ;
4506         else if (strcmp(jval,"c") == 0)
4507           emitSKPNC;
4508         else {
4509           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4510           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4511         }
4512
4513         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4514         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4515
4516     }
4517
4518
4519     /* mark the icode as generated */
4520     ic->generated = 1;
4521 }
4522
4523 #if 0
4524 // not needed ATM
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genSkip                                                         */
4528 /*-----------------------------------------------------------------*/
4529 static void genSkip(iCode *ifx,int status_bit)
4530 {
4531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4532   if(!ifx)
4533     return;
4534
4535   if ( IC_TRUE(ifx) ) {
4536     switch(status_bit) {
4537     case 'z':
4538       emitSKPNZ;
4539       break;
4540
4541     case 'c':
4542       emitSKPNC;
4543       break;
4544
4545     case 'd':
4546       emitSKPDC;
4547       break;
4548
4549     }
4550
4551     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4552     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4553
4554   } else {
4555
4556     switch(status_bit) {
4557
4558     case 'z':
4559       emitSKPZ;
4560       break;
4561
4562     case 'c':
4563       emitSKPC;
4564       break;
4565
4566     case 'd':
4567       emitSKPDC;
4568       break;
4569     }
4570     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4571     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4572
4573   }
4574
4575 }
4576 #endif
4577
4578 /*-----------------------------------------------------------------*/
4579 /* genSkipc                                                        */
4580 /*-----------------------------------------------------------------*/
4581 static void genSkipc(resolvedIfx *rifx)
4582 {
4583   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4584   
4585   if(!rifx)
4586     return;
4587
4588   if(rifx->condition)
4589     emitSKPC;
4590   else
4591     emitSKPNC;
4592
4593   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4594   rifx->generated = 1;
4595 }
4596
4597 /*-----------------------------------------------------------------*/
4598 /* genSkipz2                                                       */
4599 /*-----------------------------------------------------------------*/
4600 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4601 {
4602   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4603   
4604   if(!rifx)
4605     return;
4606
4607   if( (rifx->condition ^ invert_condition) & 1)
4608     emitSKPZ;
4609   else
4610     emitSKPNZ;
4611
4612   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4613   rifx->generated = 1;
4614 }
4615
4616 #if 0
4617 /*-----------------------------------------------------------------*/
4618 /* genSkipz                                                        */
4619 /*-----------------------------------------------------------------*/
4620 static void genSkipz(iCode *ifx, int condition)
4621 {
4622   if(!ifx)
4623     return;
4624
4625   if(condition)
4626     emitSKPNZ;
4627   else
4628     emitSKPZ;
4629
4630   if ( IC_TRUE(ifx) )
4631     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4632   else
4633     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4634
4635   if ( IC_TRUE(ifx) )
4636     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4637   else
4638     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4639
4640 }
4641 #endif
4642
4643 /*-----------------------------------------------------------------*/
4644 /* genSkipCond                                                     */
4645 /*-----------------------------------------------------------------*/
4646 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4647 {
4648   if(!rifx)
4649     return;
4650
4651   if(rifx->condition)
4652     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4653   else
4654     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4655
4656
4657   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4658   rifx->generated = 1;
4659 }
4660
4661 #if 0
4662 /*-----------------------------------------------------------------*/
4663 /* genChkZeroes :- greater or less than comparison                 */
4664 /*     For each byte in a literal that is zero, inclusive or the   */
4665 /*     the corresponding byte in the operand with W                */
4666 /*     returns true if any of the bytes are zero                   */
4667 /*-----------------------------------------------------------------*/
4668 static int genChkZeroes(operand *op, int lit,  int size)
4669 {
4670
4671   int i;
4672   int flag =1;
4673
4674   while(size--) {
4675     i = (lit >> (size*8)) & 0xff;
4676
4677     if(i==0) {
4678       if(flag) 
4679         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4680       else
4681         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4682       flag = 0;
4683     }
4684   }
4685
4686   return (flag==0);
4687 }
4688 #endif
4689
4690 /*-----------------------------------------------------------------*/
4691 /* genCmp :- greater or less than comparison                       */
4692 /*-----------------------------------------------------------------*/
4693 #if 1
4694                 /* { */
4695       /* original code */
4696 static void genCmp (operand *left,operand *right,
4697                     operand *result, iCode *ifx, int sign)
4698 {
4699   int size; //, offset = 0 ;
4700   unsigned long lit = 0L,i = 0;
4701   resolvedIfx rFalseIfx;
4702   //  resolvedIfx rTrueIfx;
4703   symbol *truelbl;
4704   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4705 /*
4706   if(ifx) {
4707     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4708     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4709   }
4710 */
4711
4712   resolveIfx(&rFalseIfx,ifx);
4713   truelbl  = newiTempLabel(NULL);
4714   size = max(AOP_SIZE(left),AOP_SIZE(right));
4715
4716   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4717
4718 #define _swapp
4719
4720   /* if literal is on the right then swap with left */
4721   if ((AOP_TYPE(right) == AOP_LIT)) {
4722     operand *tmp = right ;
4723     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4724     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4725 #ifdef _swapp
4726
4727     lit = (lit - 1) & mask;
4728     right = left;
4729     left = tmp;
4730     rFalseIfx.condition ^= 1;
4731 #endif
4732
4733   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4734     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4735   }
4736
4737
4738   //if(IC_TRUE(ifx) == NULL)
4739   /* if left & right are bit variables */
4740   if (AOP_TYPE(left) == AOP_CRY &&
4741       AOP_TYPE(right) == AOP_CRY ) {
4742     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4743     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4744   } else {
4745     /* subtract right from left if at the
4746        end the carry flag is set then we know that
4747        left is greater than right */
4748
4749     symbol *lbl  = newiTempLabel(NULL);
4750
4751 #if 0
4752         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4753                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4754 #endif
4755
4756 #ifndef _swapp
4757     if(AOP_TYPE(right) == AOP_LIT) {
4758
4759       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4760
4761       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4762
4763       /* special cases */
4764
4765       if(lit == 0) {
4766
4767         if(sign != 0) 
4768           genSkipCond(&rFalseIfx,left,size-1,7);
4769         else 
4770           /* no need to compare to 0...*/
4771           /* NOTE: this is a de-generate compare that most certainly 
4772            *       creates some dead code. */
4773           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4774
4775         if(ifx) ifx->generated = 1;
4776         return;
4777
4778       }
4779       size--;
4780
4781       if(size == 0) {
4782         //i = (lit >> (size*8)) & 0xff;
4783         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4784         
4785         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4786
4787         i = ((0-lit) & 0xff);
4788         if(sign) {
4789           if( i == 0x81) { 
4790             /* lit is 0x7f, all signed chars are less than
4791              * this except for 0x7f itself */
4792             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4793             genSkipz2(&rFalseIfx,0);
4794           } else {
4795             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4796             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4797             genSkipc(&rFalseIfx);
4798           }
4799
4800         } else {
4801           if(lit == 1) {
4802             genSkipz2(&rFalseIfx,1);
4803           } else {
4804             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4805             genSkipc(&rFalseIfx);
4806           }
4807         }
4808
4809         if(ifx) ifx->generated = 1;
4810         return;
4811       }
4812
4813       /* chars are out of the way. now do ints and longs */
4814
4815
4816       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4817         
4818       /* special cases */
4819
4820       if(sign) {
4821
4822         if(lit == 0) {
4823           genSkipCond(&rFalseIfx,left,size,7);
4824           if(ifx) ifx->generated = 1;
4825           return;
4826         }
4827
4828         if(lit <0x100) {
4829           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4830
4831           //rFalseIfx.condition ^= 1;
4832           //genSkipCond(&rFalseIfx,left,size,7);
4833           //rFalseIfx.condition ^= 1;
4834
4835           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4836           if(rFalseIfx.condition)
4837             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4838           else
4839             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4840
4841           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4842           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4843           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4844
4845           while(size > 1)
4846             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4847
4848           if(rFalseIfx.condition) {
4849             emitSKPZ;
4850             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4851
4852           } else {
4853             emitSKPNZ;
4854           }
4855
4856           genSkipc(&rFalseIfx);
4857           pic16_emitpLabel(truelbl->key);
4858           if(ifx) ifx->generated = 1;
4859           return;
4860
4861         }
4862
4863         if(size == 1) {
4864
4865           if( (lit & 0xff) == 0) {
4866             /* lower byte is zero */
4867             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4868             i = ((lit >> 8) & 0xff) ^0x80;
4869             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4870             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4871             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4872             genSkipc(&rFalseIfx);
4873
4874
4875             if(ifx) ifx->generated = 1;
4876             return;
4877
4878           }
4879         } else {
4880           /* Special cases for signed longs */
4881           if( (lit & 0xffffff) == 0) {
4882             /* lower byte is zero */
4883             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4884             i = ((lit >> 8*3) & 0xff) ^0x80;
4885             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4886             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4887             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4888             genSkipc(&rFalseIfx);
4889
4890
4891             if(ifx) ifx->generated = 1;
4892             return;
4893
4894           }
4895
4896         }
4897
4898
4899         if(lit & (0x80 << (size*8))) {
4900           /* lit is negative */
4901           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4902
4903           //genSkipCond(&rFalseIfx,left,size,7);
4904
4905           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4906
4907           if(rFalseIfx.condition)
4908             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4909           else
4910             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4911
4912
4913         } else {
4914           /* lit is positive */
4915           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4916           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4917           if(rFalseIfx.condition)
4918             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4919           else
4920             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4921
4922         }
4923
4924         /*
4925           This works, but is only good for ints.
4926           It also requires a "known zero" register.
4927           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4928           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4929           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4930           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4931           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4932           genSkipc(&rFalseIfx);
4933
4934           pic16_emitpLabel(truelbl->key);
4935           if(ifx) ifx->generated = 1;
4936           return;
4937         **/
4938           
4939         /* There are no more special cases, so perform a general compare */
4940   
4941         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4942         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4943
4944         while(size--) {
4945
4946           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4947           emitSKPNZ;
4948           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4949         }
4950         //rFalseIfx.condition ^= 1;
4951         genSkipc(&rFalseIfx);
4952
4953         pic16_emitpLabel(truelbl->key);
4954
4955         if(ifx) ifx->generated = 1;
4956         return;
4957
4958
4959       }
4960
4961
4962       /* sign is out of the way. So now do an unsigned compare */
4963       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4964
4965
4966       /* General case - compare to an unsigned literal on the right.*/
4967
4968       i = (lit >> (size*8)) & 0xff;
4969       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4970       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4971       while(size--) {
4972         i = (lit >> (size*8)) & 0xff;
4973
4974         if(i) {
4975           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4976           emitSKPNZ;
4977           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4978         } else {
4979           /* this byte of the lit is zero, 
4980            *if it's not the last then OR in the variable */
4981           if(size)
4982             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4983         }
4984       }
4985
4986
4987       pic16_emitpLabel(lbl->key);
4988 //      pic16_emitpLabel(truelbl->key);
4989       //if(emitFinalCheck)
4990       genSkipc(&rFalseIfx);
4991       if(sign)
4992         pic16_emitpLabel(truelbl->key);
4993
4994       if(ifx) ifx->generated = 1;
4995       return;
4996
4997
4998     }
4999 #endif  // _swapp
5000
5001     if(AOP_TYPE(left) == AOP_LIT) {
5002       //symbol *lbl = newiTempLabel(NULL);
5003
5004       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5005
5006
5007       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5008
5009       /* Special cases */
5010       if((lit == 0) && (sign == 0)){
5011
5012         size--;
5013         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5014         while(size) 
5015           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5016
5017         genSkipz2(&rFalseIfx,0);
5018         if(ifx) ifx->generated = 1;
5019         return;
5020       }
5021
5022       if(size==1) {
5023         /* Special cases */
5024         lit &= 0xff;
5025         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5026           /* degenerate compare can never be true */
5027           if(rFalseIfx.condition == 0)
5028             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5029
5030           if(ifx) ifx->generated = 1;
5031           return;
5032         }
5033
5034         if(sign) {
5035           /* signed comparisons to a literal byte */
5036
5037           int lp1 = (lit+1) & 0xff;
5038
5039           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5040           switch (lp1) {
5041           case 0:
5042             rFalseIfx.condition ^= 1;
5043             genSkipCond(&rFalseIfx,right,0,7);
5044             break;
5045           case 0x7f:
5046             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5047             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5048             genSkipz2(&rFalseIfx,1);
5049             break;
5050           default:
5051             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5052             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5053             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5054             rFalseIfx.condition ^= 1;
5055             genSkipc(&rFalseIfx);
5056             break;
5057           }
5058         } else {
5059           /* unsigned comparisons to a literal byte */
5060
5061           switch(lit & 0xff ) {
5062           case 0:
5063             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5064             genSkipz2(&rFalseIfx,0);
5065             break;
5066           case 0x7f:
5067             rFalseIfx.condition ^= 1;
5068             genSkipCond(&rFalseIfx,right,0,7);
5069             break;
5070
5071           default:
5072             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5073             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5074             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5075             rFalseIfx.condition ^= 1;
5076             if (AOP_TYPE(result) == AOP_CRY)
5077               genSkipc(&rFalseIfx);
5078             else {
5079               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5080               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5081             }         
5082             break;
5083           }
5084         }
5085
5086         if(ifx) ifx->generated = 1;
5087         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5088                 goto check_carry;
5089         return;
5090
5091       } else {
5092
5093         /* Size is greater than 1 */
5094
5095         if(sign) {
5096           int lp1 = lit+1;
5097
5098           size--;
5099
5100           if(lp1 == 0) {
5101             /* this means lit = 0xffffffff, or -1 */
5102
5103
5104             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5105             rFalseIfx.condition ^= 1;
5106             genSkipCond(&rFalseIfx,right,size,7);
5107             if(ifx) ifx->generated = 1;
5108
5109             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5110               goto check_carry;
5111
5112             return;
5113           }
5114
5115           if(lit == 0) {
5116             int s = size;
5117
5118             if(rFalseIfx.condition) {
5119               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5120               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5121             }
5122
5123             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5124             while(size--)
5125               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5126
5127
5128             emitSKPZ;
5129             if(rFalseIfx.condition) {
5130               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5131               pic16_emitpLabel(truelbl->key);
5132             }else {
5133               rFalseIfx.condition ^= 1;
5134               genSkipCond(&rFalseIfx,right,s,7);
5135             }
5136
5137             if(ifx) ifx->generated = 1;
5138
5139             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5140               goto check_carry;
5141
5142             return;
5143           }
5144
5145           if((size == 1) &&  (0 == (lp1&0xff))) {
5146             /* lower byte of signed word is zero */
5147             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5148             i = ((lp1 >> 8) & 0xff) ^0x80;
5149             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5150             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5151             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5152             rFalseIfx.condition ^= 1;
5153             genSkipc(&rFalseIfx);
5154
5155
5156             if(ifx) ifx->generated = 1;
5157
5158             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5159               goto check_carry;
5160
5161             return;
5162           }
5163
5164           if(lit & (0x80 << (size*8))) {
5165             /* Lit is less than zero */
5166             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5167             //rFalseIfx.condition ^= 1;
5168             //genSkipCond(&rFalseIfx,left,size,7);
5169             //rFalseIfx.condition ^= 1;
5170             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5171             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5172
5173             if(rFalseIfx.condition)
5174               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5175             else
5176               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5177
5178
5179           } else {
5180             /* Lit is greater than or equal to zero */
5181             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5182             //rFalseIfx.condition ^= 1;
5183             //genSkipCond(&rFalseIfx,right,size,7);
5184             //rFalseIfx.condition ^= 1;
5185
5186             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5187             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5188
5189             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5190             if(rFalseIfx.condition)
5191               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5192             else
5193               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5194
5195           }
5196
5197           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5198           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5199
5200           while(size--) {
5201
5202             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5203             emitSKPNZ;
5204             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5205           }
5206           rFalseIfx.condition ^= 1;
5207           //rFalseIfx.condition = 1;
5208           genSkipc(&rFalseIfx);
5209
5210           pic16_emitpLabel(truelbl->key);
5211
5212           if(ifx) ifx->generated = 1;
5213
5214
5215           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5216             goto check_carry;
5217
5218           return;
5219           // end of if (sign)
5220         } else {
5221
5222           /* compare word or long to an unsigned literal on the right.*/
5223
5224
5225           size--;
5226           if(lit < 0xff) {
5227             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5228             switch (lit) {
5229             case 0:
5230               break; /* handled above */
5231 /*
5232             case 0xff:
5233               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5234               while(size--)
5235                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5236               genSkipz2(&rFalseIfx,0);
5237               break;
5238 */
5239             default:
5240               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5241               while(--size)
5242                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5243
5244               emitSKPZ;
5245               if(rFalseIfx.condition)
5246                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5247               else
5248                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5249
5250
5251               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5252               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5253
5254               rFalseIfx.condition ^= 1;
5255               genSkipc(&rFalseIfx);
5256             }
5257
5258             pic16_emitpLabel(truelbl->key);
5259
5260             if(ifx) ifx->generated = 1;
5261
5262             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5263               goto check_carry;
5264
5265             return;
5266           }
5267
5268
5269           lit++;
5270           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5271           i = (lit >> (size*8)) & 0xff;
5272
5273           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5274           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5275
5276           while(size--) {
5277             i = (lit >> (size*8)) & 0xff;
5278
5279             if(i) {
5280               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5281               emitSKPNZ;
5282               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5283             } else {
5284               /* this byte of the lit is zero, 
5285                * if it's not the last then OR in the variable */
5286               if(size)
5287                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5288             }
5289           }
5290
5291
5292           pic16_emitpLabel(lbl->key);
5293
5294           rFalseIfx.condition ^= 1;
5295
5296           genSkipc(&rFalseIfx);
5297         }
5298
5299         if(sign)
5300           pic16_emitpLabel(truelbl->key);
5301         if(ifx) ifx->generated = 1;
5302
5303             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5304               goto check_carry;
5305
5306         return;
5307       }
5308     }
5309     /* Compare two variables */
5310
5311     DEBUGpic16_emitcode(";sign","%d",sign);
5312
5313     size--;
5314     if(sign) {
5315       /* Sigh. thus sucks... */
5316       if(size) {
5317         pCodeOp *pctemp;
5318         
5319         pctemp = pic16_popGetTempReg(1);
5320         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5322         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5323         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5324         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5325         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5326         pic16_popReleaseTempReg(pctemp, 1);
5327       } else {
5328         /* Signed char comparison */
5329         /* Special thanks to Nikolai Golovchenko for this snippet */
5330         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5331         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5332         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5333         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5334         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5335         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5336
5337         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5338         genSkipc(&rFalseIfx);
5339           
5340         if(ifx) ifx->generated = 1;
5341
5342             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5343               goto check_carry;
5344
5345         return;
5346       }
5347
5348     } else {
5349
5350       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5351       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5352     }
5353
5354
5355     /* The rest of the bytes of a multi-byte compare */
5356     while (size) {
5357
5358       emitSKPZ;
5359       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5360       size--;
5361
5362       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5363       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5364
5365
5366     }
5367
5368     pic16_emitpLabel(lbl->key);
5369
5370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5371     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5372         (AOP_TYPE(result) == AOP_REG)) {
5373       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5374       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5375     } else {
5376       genSkipc(&rFalseIfx);
5377     }         
5378     //genSkipc(&rFalseIfx);
5379     if(ifx) ifx->generated = 1;
5380
5381
5382             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5383               goto check_carry;
5384
5385     return;
5386
5387   }
5388
5389 check_carry:
5390   if ((AOP_TYPE(result) != AOP_CRY) 
5391         && AOP_SIZE(result)) {
5392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5393
5394     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5395
5396     pic16_outBitC(result);
5397   } else {
5398     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5399     /* if the result is used in the next
5400        ifx conditional branch then generate
5401        code a little differently */
5402     if (ifx )
5403       genIfxJump (ifx,"c");
5404     else
5405       pic16_outBitC(result);
5406     /* leave the result in acc */
5407   }
5408
5409 }
5410
5411 #else   /* old version of genCmp() */   /* } else { */
5412
5413 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5414 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5415         operand *result, int offset, int invert_op)
5416 {
5417   /* add code here */
5418   
5419   /* check condition, > or < ?? */
5420   if(rIfx->condition != 0)invert_op ^= 1;
5421   
5422   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5423
5424   if(!ifx)invert_op ^= 1;
5425
5426   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5427       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5428   
5429   /* do selection */
5430   if(!invert_op)return POC_CPFSGT;
5431   else return POC_CPFSLT;
5432 }
5433
5434 static int compareAopfirstpass=1;
5435
5436 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5437             operand *oper, int offset, operand *result,
5438             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5439             symbol *tlbl)
5440 {
5441   int op;
5442   symbol *truelbl;
5443
5444   /* invert if there is a result to be loaded, in order to fit,
5445    * SETC/CLRC sequence */
5446   if(AOP_SIZE(result))invert_op ^= 1;
5447
5448 //  if(sign && !offset)invert_op ^= 1;
5449   
5450 //  if(sign)invert_op ^= 1;
5451   
5452   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5453
5454   if(AOP_SIZE(result) && compareAopfirstpass) {
5455     if(!ifx) {
5456       if(pcop2)
5457         pic16_emitpcode(POC_SETF, pcop2);
5458       else
5459         emitSETC;
5460     } else {
5461       if(pcop2)
5462         pic16_emitpcode(POC_CLRF, pcop2);
5463       else
5464         emitCLRC;
5465     }
5466   }
5467
5468   compareAopfirstpass = 0;
5469
5470       /* there is a bug when comparing operands with size > 1,
5471        * because higher bytes can be equal and test should be performed
5472        * to the next lower byte, current algorithm, considers operands
5473        * inequal in these cases! -- VR 20041107 */
5474
5475     
5476   if(pcop)
5477     pic16_emitpcode(op, pcop);
5478   else
5479     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5480
5481
5482   if((!sign || !offset) && AOP_SIZE(result)) {
5483     if(!ifx) {
5484       if(pcop2)
5485         pic16_emitpcode(POC_CLRF, pcop2);
5486         else
5487         emitCLRC;
5488     } else {
5489       if(pcop2)
5490         pic16_emitpcode(POC_SETF, pcop2);
5491       else
5492         emitSETC;
5493     }
5494     
5495     /* don't emit final branch (offset == 0) */
5496     if(offset) {
5497
5498       if(pcop2)
5499         pic16_emitpcode(POC_RRCF, pcop2);
5500
5501       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5502     }
5503   } else {
5504     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5505       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5506             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5507
5508       truelbl = newiTempLabel( NULL );
5509       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5510       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5511         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5512       else
5513         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5514       pic16_emitpLabel(truelbl->key);
5515     } else {
5516       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5517     }
5518   }
5519 }
5520
5521
5522   
5523
5524 #if 1   /* { */
5525 static void genCmp (operand *left, operand *right,
5526                     operand *result, iCode *ifx, int sign)
5527 {
5528   int size, cmpop=1;
5529   long lit = 0L;
5530   resolvedIfx rFalseIfx;
5531   symbol *falselbl, *tlbl;
5532
5533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5534     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5535
5536     resolveIfx(&rFalseIfx, ifx);
5537     size = max(AOP_SIZE(left), AOP_SIZE(right));
5538     
5539     /* if left & right are bit variables */
5540     if(AOP_TYPE(left) == AOP_CRY
5541       && AOP_TYPE(right) == AOP_CRY ) {
5542
5543         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5544         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5545         
5546         werror(W_POSSBUG2, __FILE__, __LINE__);
5547         exit(-1);
5548     }
5549     
5550     /* if literal is on the right then swap with left */
5551     if((AOP_TYPE(right) == AOP_LIT)) {
5552       operand *tmp = right ;
5553 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5554
5555         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5556
5557 //      lit = (lit - 1) & mask;
5558         right = left;
5559         left = tmp;
5560         rFalseIfx.condition ^= 1;               /* reverse compare */
5561     } else
5562     if ((AOP_TYPE(left) == AOP_LIT)) {
5563       /* float compares are handled by support functions */
5564       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5565     }
5566
5567     /* actual comparing algorithm */
5568 //    size = AOP_SIZE( right );
5569
5570     falselbl = newiTempLabel( NULL );
5571     if(AOP_TYPE(left) == AOP_LIT) {
5572       /* compare to literal */
5573       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5574       
5575       if(sign) {
5576         pCodeOp *pct, *pct2;
5577         symbol *tlbl1;
5578
5579         /* signed compare */
5580         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5581
5582         pct = pic16_popCopyReg(&pic16_pc_prodl);
5583         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5584         tlbl = newiTempLabel( NULL );
5585         
5586         /* first compare signs:
5587          *  a. if both are positive, compare just like unsigned
5588          *  b. if both are negative, invert cmpop, compare just like unsigned
5589          *  c. if different signs, determine the result directly */
5590
5591         size--;
5592
5593 #if 1
5594         /* { */
5595         tlbl1 = newiTempLabel( NULL );
5596 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5597
5598         if(lit > 0) {
5599
5600           /* literal is zero or positive:
5601            *  a. if carry is zero, too, continue compare,
5602            *  b. if carry is set, then continue depending on cmpop ^ condition:
5603            *    1. '<' return false (literal < variable),
5604            *    2. '>' return true (literal > variable) */
5605 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5606           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5607           
5608           
5609           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5610           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5611         } else 
5612         if(lit < 0) {
5613           
5614           /* literal is negative:
5615            *  a. if carry is set, too, continue compare,
5616            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5617            *    1. '<' return true (literal < variable),
5618            *    2. '>' return false (literal > variable) */
5619 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5620           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5621           
5622           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5623           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5624         }
5625 #if 1
5626         else {
5627           /* lit == 0 */
5628           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5629           
5630           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5631           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5632         }
5633 #endif
5634         
5635         
5636         pic16_emitpLabel( tlbl1->key );
5637 #endif  /* } */
5638
5639         compareAopfirstpass=1;
5640 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5641 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5642 //        pic16_emitpcode(POC_MOVWF, pct);
5643
5644 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5645         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5646 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5647         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5648
5649         /* generic case */        
5650           while( size-- ) {
5651 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5652 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5653 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5654 //            pic16_emitpcode(POC_MOVWF, pct);
5655
5656 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5657             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5658             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5659 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5660 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5661           }
5662 //        }
5663         
5664         if(ifx)ifx->generated = 1;
5665
5666         if(AOP_SIZE(result)) {
5667           pic16_emitpLabel(tlbl->key);
5668           pic16_emitpLabel(falselbl->key);
5669           pic16_outBitOp( result, pct2 );
5670         } else {
5671           pic16_emitpLabel(tlbl->key);
5672         }
5673       } else {
5674
5675
5676         /* unsigned compare */      
5677         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5678     
5679         compareAopfirstpass=1;
5680         while(size--) {
5681           
5682           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5683           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5684
5685         }
5686
5687         if(ifx)ifx->generated = 1;
5688
5689
5690         if(AOP_SIZE(result)) {
5691           pic16_emitpLabel(falselbl->key);
5692           pic16_outBitC( result );
5693         }
5694
5695       }
5696     } else {
5697       /* compare registers */
5698       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5699
5700
5701       if(sign) {
5702         pCodeOp *pct, *pct2;
5703         
5704         /* signed compare */
5705         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5706
5707         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
5708         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
5709         tlbl = newiTempLabel( NULL );
5710         
5711         compareAopfirstpass=1;
5712
5713         size--;
5714         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5715 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5716         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5717         pic16_emitpcode(POC_MOVWF, pct);
5718
5719         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5720 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5721         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5722
5723         /* WREG already holds left + 0x80 */
5724         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5725         
5726         while( size-- ) {
5727           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5728 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5729           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5730           pic16_emitpcode(POC_MOVWF, pct);
5731                 
5732           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5733 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5734           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5735
5736           /* WREG already holds left + 0x80 */
5737           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5738 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5739         }
5740         
5741         if(ifx)ifx->generated = 1;
5742
5743         if(AOP_SIZE(result)) {
5744           pic16_emitpLabel(tlbl->key);
5745           pic16_emitpLabel(falselbl->key);
5746           pic16_outBitOp( result, pct2 );
5747         } else {
5748           pic16_emitpLabel(tlbl->key);
5749         }
5750
5751       } else {
5752         /* unsigned compare */      
5753         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5754
5755         compareAopfirstpass=1;
5756         while(size--) {
5757           
5758           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5759           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5760
5761         }
5762
5763         if(ifx)ifx->generated = 1;
5764         if(AOP_SIZE(result)) {
5765
5766           pic16_emitpLabel(falselbl->key);
5767           pic16_outBitC( result );
5768         }
5769
5770       }
5771     }
5772 }
5773
5774 #else    /* } else { */
5775
5776 /* new version of genCmp -- VR 20041012 */
5777 static void genCmp (operand *left,operand *right,
5778                     operand *result, iCode *ifx, int sign)
5779 {
5780   int size; //, offset = 0 ;
5781   unsigned long lit = 0L,i = 0;
5782   resolvedIfx rFalseIfx;
5783   int willCheckCarry=0;
5784   //  resolvedIfx rTrueIfx;
5785   symbol *truelbl;
5786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5787
5788
5789   /* General concept:
5790    * subtract right from left if at the end the carry flag is set then we
5791    * know that left is greater than right */
5792             
5793   resolveIfx(&rFalseIfx,ifx);
5794   truelbl  = newiTempLabel(NULL);
5795   size = max(AOP_SIZE(left),AOP_SIZE(right));
5796
5797   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5798
5799   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5800    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5801   
5802
5803   /* if literal is on the right then swap with left */
5804   if ((AOP_TYPE(right) == AOP_LIT)) {
5805     operand *tmp = right ;
5806     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5807
5808       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5809
5810 //      lit = (lit - 1) & mask;
5811       right = left;
5812       left = tmp;
5813       rFalseIfx.condition ^= 1;         /* reverse compare */
5814   } else
5815   if ((AOP_TYPE(left) == AOP_LIT)) {
5816     /* float compares are handled by support functions */
5817     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5818   }
5819
5820
5821   //if(IC_TRUE(ifx) == NULL)
5822   /* if left & right are bit variables */
5823   if (AOP_TYPE(left) == AOP_CRY &&
5824       AOP_TYPE(right) == AOP_CRY ) {
5825
5826     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5827     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5828
5829   } else {
5830     symbol *lbl  = newiTempLabel(NULL);
5831
5832     if(AOP_TYPE(left) == AOP_LIT) {
5833       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5834
5835       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5836         willCheckCarry = 1;
5837       else willCheckCarry = 0;
5838
5839       /* Special cases */
5840       if((lit == 0) && (sign == 0)) {
5841         /* unsigned compare to 0 */
5842         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5843         
5844         size--;
5845         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5846         while(size) 
5847           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5848
5849         genSkipz2(&rFalseIfx,0);
5850         if(ifx)ifx->generated = 1;
5851         return;
5852       }
5853
5854       if(size==1) {
5855         /* Special cases */
5856         lit &= 0xff;
5857         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5858           /* degenerate compare can never be true */
5859           if(rFalseIfx.condition == 0)
5860             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5861
5862           if(ifx) ifx->generated = 1;
5863           return;
5864         }
5865
5866         if(sign) {
5867           /* signed comparisons to a literal byte */
5868           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5869
5870           int lp1 = (lit+1) & 0xff;
5871
5872           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5873           switch (lp1) {
5874           case 0:
5875             rFalseIfx.condition ^= 1;
5876             genSkipCond(&rFalseIfx,right,0,7);
5877             break;
5878           case 0x7f:
5879             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5880             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5881             genSkipz2(&rFalseIfx,1);
5882             break;
5883           default:
5884             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5885             
5886             if(rFalseIfx.condition)
5887               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5888             else
5889               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5890
5891             if(willCheckCarry) {
5892               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5893               else { emitSETC; emitCLRC; }
5894               
5895             } else {
5896               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5897             }              
5898                       
5899 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5900             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5901             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5902             rFalseIfx.condition ^= 1;
5903             genSkipc(&rFalseIfx);
5904 */
5905             break;
5906           }
5907         } else {
5908           /* unsigned comparisons to a literal byte */
5909           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5910
5911           switch(lit & 0xff ) {
5912                           /* special cases */
5913           case 0:
5914             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5915             genSkipz2(&rFalseIfx,0);
5916             break;
5917           case 0x7f:
5918             rFalseIfx.condition ^= 1;
5919             genSkipCond(&rFalseIfx,right,0,7);
5920             break;
5921           default:
5922             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5923             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5924             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5925             rFalseIfx.condition ^= 1;
5926             if (AOP_TYPE(result) == AOP_CRY)
5927               genSkipc(&rFalseIfx);
5928             else {
5929               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5930               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5931             }         
5932             break;
5933           }
5934         }
5935
5936         if(ifx) ifx->generated = 1;
5937         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5938                 goto check_carry;
5939         return;
5940
5941       } else {
5942
5943         /* Size is greater than 1 */
5944
5945         if(sign) {
5946           int lp1 = lit+1;
5947
5948           size--;
5949
5950           if(lp1 == 0) {
5951             /* this means lit = 0xffffffff, or -1 */
5952
5953
5954             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5955             rFalseIfx.condition ^= 1;
5956             genSkipCond(&rFalseIfx,right,size,7);
5957             if(ifx) ifx->generated = 1;
5958             return;
5959           }
5960
5961           if(lit == 0) {
5962             int s = size;
5963
5964             if(rFalseIfx.condition) {
5965               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5966               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5967             }
5968
5969             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5970             while(size--)
5971               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5972
5973
5974             emitSKPZ;
5975             if(rFalseIfx.condition) {
5976               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5977               pic16_emitpLabel(truelbl->key);
5978             }else {
5979               rFalseIfx.condition ^= 1;
5980               genSkipCond(&rFalseIfx,right,s,7);
5981             }
5982
5983             if(ifx) ifx->generated = 1;
5984             return;
5985           }
5986
5987           if((size == 1) &&  (0 == (lp1&0xff))) {
5988             /* lower byte of signed word is zero */
5989             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5990             i = ((lp1 >> 8) & 0xff) ^0x80;
5991             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5992             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5993             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5994             rFalseIfx.condition ^= 1;
5995             genSkipc(&rFalseIfx);
5996
5997
5998             if(ifx) ifx->generated = 1;
5999             return;
6000           }
6001
6002           if(lit & (0x80 << (size*8))) {
6003             /* Lit is less than zero */
6004             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6005             //rFalseIfx.condition ^= 1;
6006             //genSkipCond(&rFalseIfx,left,size,7);
6007             //rFalseIfx.condition ^= 1;
6008             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6009             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6010
6011             if(rFalseIfx.condition)
6012               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6013             else
6014               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6015
6016
6017           } else {
6018             /* Lit is greater than or equal to zero */
6019             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6020             //rFalseIfx.condition ^= 1;
6021             //genSkipCond(&rFalseIfx,right,size,7);
6022             //rFalseIfx.condition ^= 1;
6023
6024             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6025             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6026
6027             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6028             if(rFalseIfx.condition)
6029               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6030             else
6031               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6032
6033           }
6034
6035
6036           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6037           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6038
6039           while(size--) {
6040
6041             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6042             emitSKPNZ;
6043             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6044           }
6045           rFalseIfx.condition ^= 1;
6046           //rFalseIfx.condition = 1;
6047           genSkipc(&rFalseIfx);
6048
6049           pic16_emitpLabel(truelbl->key);
6050
6051           if(ifx) ifx->generated = 1;
6052           return;
6053           // end of if (sign)
6054         } else {
6055
6056           /* compare word or long to an unsigned literal on the right.*/
6057
6058
6059           size--;
6060           if(lit < 0xff) {
6061             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6062             switch (lit) {
6063             case 0:
6064               break; /* handled above */
6065 /*
6066             case 0xff:
6067               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6068               while(size--)
6069                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6070               genSkipz2(&rFalseIfx,0);
6071               break;
6072 */
6073             default:
6074               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6075               while(--size)
6076                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6077
6078               emitSKPZ;
6079               if(rFalseIfx.condition)
6080                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6081               else
6082                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6083
6084
6085               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6086               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6087
6088               rFalseIfx.condition ^= 1;
6089               genSkipc(&rFalseIfx);
6090             }
6091
6092             pic16_emitpLabel(truelbl->key);
6093
6094             if(ifx) ifx->generated = 1;
6095             return;
6096           }
6097
6098
6099           lit++;
6100           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6101           i = (lit >> (size*8)) & 0xff;
6102
6103           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6104           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6105
6106           while(size--) {
6107             i = (lit >> (size*8)) & 0xff;
6108
6109             if(i) {
6110               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6111               emitSKPNZ;
6112               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6113             } else {
6114               /* this byte of the lit is zero, 
6115                * if it's not the last then OR in the variable */
6116               if(size)
6117                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6118             }
6119           }
6120
6121
6122           pic16_emitpLabel(lbl->key);
6123
6124           rFalseIfx.condition ^= 1;
6125
6126           genSkipc(&rFalseIfx);
6127         }
6128
6129         if(sign)
6130           pic16_emitpLabel(truelbl->key);
6131         if(ifx) ifx->generated = 1;
6132         return;
6133       }
6134     }
6135     /* Compare two variables */
6136
6137     DEBUGpic16_emitcode(";sign","%d",sign);
6138
6139     size--;
6140     if(sign) {
6141       /* Sigh. thus sucks... */
6142       if(size) {
6143         pCodeOp *pctemp;
6144         
6145         pctemp = pic16_popGetTempReg(1);
6146         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6147         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6148         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6149         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6150         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6151         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6152         pic16_popReleaseTempReg(pctemp, 1);
6153       } else {
6154         /* Signed char comparison */
6155         /* Special thanks to Nikolai Golovchenko for this snippet */
6156         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6157         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6158         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6159         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6160         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6161         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6162
6163         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6164         genSkipc(&rFalseIfx);
6165           
6166         if(ifx) ifx->generated = 1;
6167         return;
6168       }
6169
6170     } else {
6171
6172       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6173       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6174     }
6175
6176
6177     /* The rest of the bytes of a multi-byte compare */
6178     while (size) {
6179
6180       emitSKPZ;
6181       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6182       size--;
6183
6184       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6185       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6186
6187
6188     }
6189
6190     pic16_emitpLabel(lbl->key);
6191
6192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6193     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6194         (AOP_TYPE(result) == AOP_REG)) {
6195       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6196       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6197     } else {
6198       genSkipc(&rFalseIfx);
6199     }         
6200     //genSkipc(&rFalseIfx);
6201     if(ifx) ifx->generated = 1;
6202
6203     return;
6204
6205   }
6206
6207 check_carry:
6208   if ((AOP_TYPE(result) != AOP_CRY) 
6209         && AOP_SIZE(result)) {
6210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6211
6212     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6213
6214     pic16_outBitC(result);
6215   } else {
6216     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6217     /* if the result is used in the next
6218        ifx conditional branch then generate
6219        code a little differently */
6220     if (ifx )
6221       genIfxJump (ifx,"c");
6222     else
6223       pic16_outBitC(result);
6224     /* leave the result in acc */
6225   }
6226
6227 }
6228 #endif  /* } */
6229
6230
6231 #endif  /* } */
6232
6233
6234
6235 /*-----------------------------------------------------------------*/
6236 /* genCmpGt :- greater than comparison                             */
6237 /*-----------------------------------------------------------------*/
6238 static void genCmpGt (iCode *ic, iCode *ifx)
6239 {
6240     operand *left, *right, *result;
6241     sym_link *letype , *retype;
6242     int sign ;
6243
6244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245     left = IC_LEFT(ic);
6246     right= IC_RIGHT(ic);
6247     result = IC_RESULT(ic);
6248
6249     letype = getSpec(operandType(left));
6250     retype =getSpec(operandType(right));
6251     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6252     /* assign the amsops */
6253     pic16_aopOp (left,ic,FALSE);
6254     pic16_aopOp (right,ic,FALSE);
6255     pic16_aopOp (result,ic,TRUE);
6256
6257     genCmp(right, left, result, ifx, sign);
6258
6259     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261     pic16_freeAsmop(result,NULL,ic,TRUE); 
6262 }
6263
6264 /*-----------------------------------------------------------------*/
6265 /* genCmpLt - less than comparisons                                */
6266 /*-----------------------------------------------------------------*/
6267 static void genCmpLt (iCode *ic, iCode *ifx)
6268 {
6269     operand *left, *right, *result;
6270     sym_link *letype , *retype;
6271     int sign ;
6272
6273     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6274     left = IC_LEFT(ic);
6275     right= IC_RIGHT(ic);
6276     result = IC_RESULT(ic);
6277
6278     letype = getSpec(operandType(left));
6279     retype =getSpec(operandType(right));
6280     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6281
6282     /* assign the amsops */
6283     pic16_aopOp (left,ic,FALSE);
6284     pic16_aopOp (right,ic,FALSE);
6285     pic16_aopOp (result,ic,TRUE);
6286
6287     genCmp(left, right, result, ifx, sign);
6288
6289     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6290     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6291     pic16_freeAsmop(result,NULL,ic,TRUE); 
6292 }
6293
6294 #if 0
6295 // not needed ATM
6296 // FIXME reenable literal optimisation when the pic16 port is stable
6297
6298 /*-----------------------------------------------------------------*/
6299 /* genc16bit2lit - compare a 16 bit value to a literal             */
6300 /*-----------------------------------------------------------------*/
6301 static void genc16bit2lit(operand *op, int lit, int offset)
6302 {
6303   int i;
6304
6305   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6306   if( (lit&0xff) == 0) 
6307     i=1;
6308   else
6309     i=0;
6310
6311   switch( BYTEofLONG(lit,i)) { 
6312   case 0:
6313     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6314     break;
6315   case 1:
6316     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6317     break;
6318   case 0xff:
6319     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6320     break;
6321   default:
6322     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6323     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6324   }
6325
6326   i ^= 1;
6327
6328   switch( BYTEofLONG(lit,i)) { 
6329   case 0:
6330     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6331     break;
6332   case 1:
6333     emitSKPNZ;
6334     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6335     break;
6336   case 0xff:
6337     emitSKPNZ;
6338     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6339     break;
6340   default:
6341     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6342     emitSKPNZ;
6343     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6344
6345   }
6346
6347 }
6348 #endif
6349
6350 #if 0
6351 // not needed ATM
6352 /*-----------------------------------------------------------------*/
6353 /* gencjneshort - compare and jump if not equal                    */
6354 /*-----------------------------------------------------------------*/
6355 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6356 {
6357   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6358   int offset = 0;
6359   int res_offset = 0;  /* the result may be a different size then left or right */
6360   int res_size = AOP_SIZE(result);
6361   resolvedIfx rIfx;
6362   symbol *lbl, *lbl_done;
6363
6364   unsigned long lit = 0L;
6365   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6366
6367   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6368   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6369   if(result)
6370     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6371   resolveIfx(&rIfx,ifx);
6372   lbl =  newiTempLabel(NULL);
6373   lbl_done =  newiTempLabel(NULL);
6374
6375
6376   /* if the left side is a literal or 
6377      if the right is in a pointer register and left 
6378      is not */
6379   if ((AOP_TYPE(left) == AOP_LIT) || 
6380       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6381     operand *t = right;
6382     right = left;
6383     left = t;
6384   }
6385   if(AOP_TYPE(right) == AOP_LIT)
6386     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6387
6388   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6389     preserve_result = 1;
6390
6391   if(result && !preserve_result)
6392     {
6393       int i;
6394       for(i = 0; i < AOP_SIZE(result); i++)
6395         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6396     }
6397
6398
6399   /* if the right side is a literal then anything goes */
6400   if (AOP_TYPE(right) == AOP_LIT &&
6401       AOP_TYPE(left) != AOP_DIR ) {
6402     switch(size) {
6403     case 2:
6404       genc16bit2lit(left, lit, 0);
6405       emitSKPZ;
6406       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6407       break;
6408     default:
6409       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6410       while (size--) {
6411         if(lit & 0xff) {
6412           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6413           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6414         } else {
6415           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6416         }
6417
6418         emitSKPZ;
6419         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6420         offset++;
6421         if(res_offset < res_size-1)
6422           res_offset++;
6423         lit >>= 8;
6424       }
6425       break;
6426     }
6427   }
6428
6429   /* if the right side is in a register or in direct space or
6430      if the left is a pointer register & right is not */    
6431   else if (AOP_TYPE(right) == AOP_REG ||
6432            AOP_TYPE(right) == AOP_DIR || 
6433            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6434            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6435     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6436     int lbl_key = lbl->key;
6437
6438     if(result) {
6439       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6440       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6441     }else {
6442       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6443       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6444               __FUNCTION__,__LINE__);
6445       return;
6446     }
6447    
6448 /*     switch(size) { */
6449 /*     case 2: */
6450 /*       genc16bit2lit(left, lit, 0); */
6451 /*       emitSKPNZ; */
6452 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6453 /*       break; */
6454 /*     default: */
6455     while (size--) {
6456       int emit_skip=1;
6457       if((AOP_TYPE(left) == AOP_DIR) && 
6458          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6459
6460         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6461         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6462
6463       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6464             
6465         switch (lit & 0xff) {
6466         case 0:
6467           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6468           break;
6469         case 1:
6470           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6471           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6472           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6473           emit_skip=0;
6474           break;
6475         case 0xff:
6476           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6477           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6478           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6479           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6480           emit_skip=0;
6481           break;
6482         default:
6483           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6484           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6485         }
6486         lit >>= 8;
6487
6488       } else {
6489         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6490       }
6491       if(emit_skip) {
6492         if(AOP_TYPE(result) == AOP_CRY) {
6493           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6494           if(rIfx.condition)
6495             emitSKPNZ;
6496           else
6497             emitSKPZ;
6498           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6499         } else {
6500           /* fix me. probably need to check result size too */
6501           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6502           if(rIfx.condition)
6503             emitSKPZ;
6504           else
6505             emitSKPNZ;
6506           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6507           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508         }
6509         if(ifx)
6510           ifx->generated=1;
6511       }
6512       emit_skip++;
6513       offset++;
6514       if(res_offset < res_size-1)
6515         res_offset++;
6516     }
6517 /*       break; */
6518 /*     } */
6519   } else if(AOP_TYPE(right) == AOP_REG &&
6520             AOP_TYPE(left) != AOP_DIR){
6521
6522     while(size--) {
6523       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6524       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6525       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6526       if(rIfx.condition)
6527         emitSKPNZ;
6528       else
6529         emitSKPZ;
6530       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6531       offset++;
6532       if(res_offset < res_size-1)
6533         res_offset++;
6534     }
6535       
6536   }else{
6537     /* right is a pointer reg need both a & b */
6538     while(size--) {
6539       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6540       if(strcmp(l,"b"))
6541         pic16_emitcode("mov","b,%s",l);
6542       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6543       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6544       offset++;
6545     }
6546   }
6547
6548   if(result && preserve_result)
6549     {
6550       int i;
6551       for(i = 0; i < AOP_SIZE(result); i++)
6552         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6553     }
6554
6555   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6556
6557   if(result && preserve_result)
6558     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6559
6560   if(!rIfx.condition)
6561     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6562
6563   pic16_emitpLabel(lbl->key);
6564
6565   if(result && preserve_result)
6566     {
6567       int i;
6568       for(i = 0; i < AOP_SIZE(result); i++)
6569         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6570
6571       pic16_emitpLabel(lbl_done->key);
6572    }
6573
6574   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6575
6576   if(ifx)
6577     ifx->generated = 1;
6578 }
6579 #endif
6580
6581 #if 0
6582 /*-----------------------------------------------------------------*/
6583 /* gencjne - compare and jump if not equal                         */
6584 /*-----------------------------------------------------------------*/
6585 static void gencjne(operand *left, operand *right, iCode *ifx)
6586 {
6587     symbol *tlbl  = newiTempLabel(NULL);
6588
6589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6590     gencjneshort(left, right, lbl);
6591
6592     pic16_emitcode("mov","a,%s",one);
6593     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6594     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6595     pic16_emitcode("clr","a");
6596     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6597
6598     pic16_emitpLabel(lbl->key);
6599     pic16_emitpLabel(tlbl->key);
6600
6601 }
6602 #endif
6603
6604
6605 /*-----------------------------------------------------------------*/
6606 /* is_LitOp - check if operand has to be treated as literal        */
6607 /*-----------------------------------------------------------------*/
6608 static bool is_LitOp(operand *op)
6609 {
6610   return ((AOP_TYPE(op) == AOP_LIT)
6611       || ( (AOP_TYPE(op) == AOP_PCODE)
6612           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6613               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6614 }
6615
6616 /*-----------------------------------------------------------------*/
6617 /* is_LitAOp - check if operand has to be treated as literal        */
6618 /*-----------------------------------------------------------------*/
6619 static bool is_LitAOp(asmop *aop)
6620 {
6621   return ((aop->type == AOP_LIT)
6622       || ( (aop->type == AOP_PCODE)
6623           && ( (aop->aopu.pcop->type == PO_LITERAL)
6624               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6625 }
6626
6627
6628
6629 /*-----------------------------------------------------------------*/
6630 /* genCmpEq - generates code for equal to                          */
6631 /*-----------------------------------------------------------------*/
6632 static void genCmpEq (iCode *ic, iCode *ifx)
6633 {
6634   operand *left, *right, *result;
6635   symbol *falselbl = newiTempLabel(NULL);
6636   symbol *donelbl = newiTempLabel(NULL);
6637
6638   int preserve_result = 0;
6639   int generate_result = 0;
6640   int i=0;
6641
6642   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6643   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6644   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6645  
6646   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6647   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6648
6649   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6650     {
6651       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6652       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6653       goto release;
6654     }
6655
6656   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6657     {
6658       operand *tmp = right ;
6659       right = left;
6660       left = tmp;
6661     }
6662
6663   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6664     preserve_result = 1;
6665
6666   if(result && AOP_SIZE(result))
6667     generate_result = 1;
6668
6669   if(generate_result && !preserve_result)
6670     {
6671       for(i = 0; i < AOP_SIZE(result); i++)
6672         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6673     }
6674
6675   for(i=0; i < AOP_SIZE(left); i++)
6676     {
6677       if(AOP_TYPE(left) != AOP_ACC)
6678         {
6679           if(is_LitOp(left))
6680             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6681           else
6682             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6683         }
6684       if(is_LitOp(right))
6685         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6686       else
6687         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6688
6689       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6690     }
6691
6692   // result == true
6693
6694   if(generate_result && preserve_result)
6695     {
6696       for(i = 0; i < AOP_SIZE(result); i++)
6697         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6698     }
6699
6700   if(generate_result)
6701     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6702
6703   if(generate_result && preserve_result)
6704     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6705
6706   if(ifx && IC_TRUE(ifx))
6707     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6708
6709   if(ifx && IC_FALSE(ifx))
6710     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6711
6712   pic16_emitpLabel(falselbl->key);
6713
6714   // result == false
6715
6716   if(ifx && IC_FALSE(ifx))
6717     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6718
6719   if(generate_result && preserve_result)
6720     {
6721       for(i = 0; i < AOP_SIZE(result); i++)
6722         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6723     }
6724
6725   pic16_emitpLabel(donelbl->key);
6726
6727   if(ifx)
6728     ifx->generated = 1;
6729
6730 release:
6731   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6732   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6733   pic16_freeAsmop(result,NULL,ic,TRUE);
6734
6735 }
6736
6737
6738 #if 0
6739 // old version kept for reference
6740
6741 /*-----------------------------------------------------------------*/
6742 /* genCmpEq - generates code for equal to                          */
6743 /*-----------------------------------------------------------------*/
6744 static void genCmpEq (iCode *ic, iCode *ifx)
6745 {
6746     operand *left, *right, *result;
6747     unsigned long lit = 0L;
6748     int size,offset=0;
6749     symbol *falselbl  = newiTempLabel(NULL);
6750
6751
6752     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6753
6754     if(ifx)
6755       DEBUGpic16_emitcode ("; ifx is non-null","");
6756     else
6757       DEBUGpic16_emitcode ("; ifx is null","");
6758
6759     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6760     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6761     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6762
6763     size = max(AOP_SIZE(left),AOP_SIZE(right));
6764
6765     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6766
6767     /* if literal, literal on the right or 
6768     if the right is in a pointer register and left 
6769     is not */
6770     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6771         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6772       operand *tmp = right ;
6773       right = left;
6774       left = tmp;
6775     }
6776
6777
6778     if(ifx && !AOP_SIZE(result)){
6779         symbol *tlbl;
6780         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6781         /* if they are both bit variables */
6782         if (AOP_TYPE(left) == AOP_CRY &&
6783             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6784                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6785             if(AOP_TYPE(right) == AOP_LIT){
6786                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6787                 if(lit == 0L){
6788                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6789                     pic16_emitcode("cpl","c");
6790                 } else if(lit == 1L) {
6791                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6792                 } else {
6793                     pic16_emitcode("clr","c");
6794                 }
6795                 /* AOP_TYPE(right) == AOP_CRY */
6796             } else {
6797                 symbol *lbl = newiTempLabel(NULL);
6798                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6799                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6800                 pic16_emitcode("cpl","c");
6801                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6802             }
6803             /* if true label then we jump if condition
6804             supplied is true */
6805             tlbl = newiTempLabel(NULL);
6806             if ( IC_TRUE(ifx) ) {
6807                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6808                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6809             } else {
6810                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6811                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6812             }
6813             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6814
6815                 {
6816                 /* left and right are both bit variables, result is carry */
6817                         resolvedIfx rIfx;
6818               
6819                         resolveIfx(&rIfx,ifx);
6820
6821                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6822                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6823                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6824                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6825                         genSkipz2(&rIfx,0);
6826                 }
6827         } else {
6828
6829                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6830
6831                         /* They're not both bit variables. Is the right a literal? */
6832                         if(AOP_TYPE(right) == AOP_LIT) {
6833                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6834             
6835                         switch(size) {
6836
6837                                 case 1:
6838                                         switch(lit & 0xff) {
6839                                                 case 1:
6840                                                                 if ( IC_TRUE(ifx) ) {
6841                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6842                                                                         emitSKPNZ;
6843                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6844                                                                 } else {
6845                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6846                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6847                                                                 }
6848                                                                 break;
6849                                                 case 0xff:
6850                                                                 if ( IC_TRUE(ifx) ) {
6851                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6852                                                                         emitSKPNZ;
6853                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6854                                                                 } else {
6855                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6856                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6857                                                                 }
6858                                                                 break;
6859                                                 default:
6860                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6861                                                                 if(lit)
6862                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6863                                                                 genSkip(ifx,'z');
6864                                         } // switch lit
6865
6866
6867                                         /* end of size == 1 */
6868                                         break;
6869               
6870                                 case 2:
6871                                         genc16bit2lit(left,lit,offset);
6872                                         genSkip(ifx,'z');
6873                                         break;
6874                                         /* end of size == 2 */
6875
6876                                 default:
6877                                         /* size is 4 */
6878                                         if(lit==0) {
6879                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6880                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6881                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6882                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6883                                                 genSkip(ifx,'z');
6884                                         } else {
6885                                                 /* search for patterns that can be optimized */
6886
6887                                                 genc16bit2lit(left,lit,0);
6888                                                 lit >>= 16;
6889                                                 if(lit) {
6890                                                                 if(IC_TRUE(ifx))
6891                                                                 emitSKPZ; // if hi word unequal
6892                                                                 else
6893                                                                 emitSKPNZ; // if hi word equal
6894                                                                 // fail early
6895                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6896                                                         genc16bit2lit(left,lit,2);
6897                                                         genSkip(ifx,'z');
6898                                                 } else {
6899                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6900                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6901                                                         genSkip(ifx,'z');
6902                                                 }
6903                                         }
6904                                                 pic16_emitpLabel(falselbl->key);
6905                                                 break;
6906
6907                         } // switch size
6908           
6909                         ifx->generated = 1;
6910                         goto release ;
6911             
6912
6913           } else if(AOP_TYPE(right) == AOP_CRY ) {
6914             /* we know the left is not a bit, but that the right is */
6915             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6916             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6917                       pic16_popGet(AOP(right),offset));
6918             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6919
6920             /* if the two are equal, then W will be 0 and the Z bit is set
6921              * we could test Z now, or go ahead and check the high order bytes if
6922              * the variable we're comparing is larger than a byte. */
6923
6924             while(--size)
6925               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6926
6927             if ( IC_TRUE(ifx) ) {
6928               emitSKPNZ;
6929               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6930               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6931             } else {
6932               emitSKPZ;
6933               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6934               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6935             }
6936
6937           } else {
6938             /* They're both variables that are larger than bits */
6939             int s = size;
6940
6941             tlbl = newiTempLabel(NULL);
6942
6943             while(size--) {
6944               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6945               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6946
6947               if ( IC_TRUE(ifx) ) {
6948                 if(size) {
6949                   emitSKPZ;
6950                 
6951                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6952
6953                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6954                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6955                 } else {
6956                   emitSKPNZ;
6957
6958                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6959
6960
6961                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6962                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6963                 }
6964               } else {
6965                 emitSKPZ;
6966
6967                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6968
6969                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6970                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6971               }
6972               offset++;
6973             }
6974             if(s>1 && IC_TRUE(ifx)) {
6975               pic16_emitpLabel(tlbl->key);
6976               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6977             }
6978           }
6979         }
6980         /* mark the icode as generated */
6981         ifx->generated = 1;
6982         goto release ;
6983     }
6984
6985     /* if they are both bit variables */
6986     if (AOP_TYPE(left) == AOP_CRY &&
6987         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6988         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6989         if(AOP_TYPE(right) == AOP_LIT){
6990             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6991             if(lit == 0L){
6992                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6993                 pic16_emitcode("cpl","c");
6994             } else if(lit == 1L) {
6995                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6996             } else {
6997                 pic16_emitcode("clr","c");
6998             }
6999             /* AOP_TYPE(right) == AOP_CRY */
7000         } else {
7001             symbol *lbl = newiTempLabel(NULL);
7002             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7003             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7004             pic16_emitcode("cpl","c");
7005             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7006         }
7007         /* c = 1 if egal */
7008         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7009             pic16_outBitC(result);
7010             goto release ;
7011         }
7012         if (ifx) {
7013             genIfxJump (ifx,"c");
7014             goto release ;
7015         }
7016         /* if the result is used in an arithmetic operation
7017         then put the result in place */
7018         pic16_outBitC(result);
7019     } else {
7020       
7021       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7022       gencjne(left,right,result,ifx);
7023 /*
7024       if(ifx) 
7025         gencjne(left,right,newiTempLabel(NULL));
7026       else {
7027         if(IC_TRUE(ifx)->key)
7028           gencjne(left,right,IC_TRUE(ifx)->key);
7029         else
7030           gencjne(left,right,IC_FALSE(ifx)->key);
7031         ifx->generated = 1;
7032         goto release ;
7033       }
7034       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7035         pic16_aopPut(AOP(result),"a",0);
7036         goto release ;
7037       }
7038
7039       if (ifx) {
7040         genIfxJump (ifx,"a");
7041         goto release ;
7042       }
7043 */
7044       /* if the result is used in an arithmetic operation
7045          then put the result in place */
7046 /*
7047       if (AOP_TYPE(result) != AOP_CRY) 
7048         pic16_outAcc(result);
7049 */
7050       /* leave the result in acc */
7051     }
7052
7053 release:
7054     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7055     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7056     pic16_freeAsmop(result,NULL,ic,TRUE);
7057 }
7058 #endif
7059
7060 /*-----------------------------------------------------------------*/
7061 /* ifxForOp - returns the icode containing the ifx for operand     */
7062 /*-----------------------------------------------------------------*/
7063 static iCode *ifxForOp ( operand *op, iCode *ic )
7064 {
7065     /* if true symbol then needs to be assigned */
7066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7067     if (IS_TRUE_SYMOP(op))
7068         return NULL ;
7069
7070     /* if this has register type condition and
7071     the next instruction is ifx with the same operand
7072     and live to of the operand is upto the ifx only then */
7073     if (ic->next
7074         && ic->next->op == IFX
7075         && IC_COND(ic->next)->key == op->key
7076         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7077         ) {
7078                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7079           return ic->next;
7080     }
7081
7082     if (ic->next &&
7083         ic->next->op == IFX &&
7084         IC_COND(ic->next)->key == op->key) {
7085       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7086       return ic->next;
7087     }
7088
7089     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7090     if (ic->next &&
7091         ic->next->op == IFX)
7092       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7093
7094     if (ic->next &&
7095         ic->next->op == IFX &&
7096         IC_COND(ic->next)->key == op->key) {
7097       DEBUGpic16_emitcode ("; "," key is okay");
7098       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7099                            OP_SYMBOL(op)->liveTo,
7100                            ic->next->seq);
7101     }
7102
7103 #if 0
7104     /* the code below is completely untested
7105      * it just allows ulong2fs.c compile -- VR */
7106          
7107     ic = ic->next;
7108     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7109                                         __FILE__, __FUNCTION__, __LINE__);
7110         
7111     /* if this has register type condition and
7112     the next instruction is ifx with the same operand
7113     and live to of the operand is upto the ifx only then */
7114     if (ic->next &&
7115         ic->next->op == IFX &&
7116         IC_COND(ic->next)->key == op->key &&
7117         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7118         return ic->next;
7119
7120     if (ic->next &&
7121         ic->next->op == IFX &&
7122         IC_COND(ic->next)->key == op->key) {
7123       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7124       return ic->next;
7125     }
7126
7127     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7128                                         __FILE__, __FUNCTION__, __LINE__);
7129
7130 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7131 #endif
7132
7133     return NULL;
7134 }
7135 /*-----------------------------------------------------------------*/
7136 /* genAndOp - for && operation                                     */
7137 /*-----------------------------------------------------------------*/
7138 static void genAndOp (iCode *ic)
7139 {
7140     operand *left,*right, *result;
7141 /*     symbol *tlbl; */
7142
7143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7144     /* note here that && operations that are in an
7145     if statement are taken away by backPatchLabels
7146     only those used in arthmetic operations remain */
7147     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7148     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7149     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7150
7151     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7152
7153     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7154     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7155     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7156
7157     /* if both are bit variables */
7158 /*     if (AOP_TYPE(left) == AOP_CRY && */
7159 /*         AOP_TYPE(right) == AOP_CRY ) { */
7160 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7161 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7162 /*         pic16_outBitC(result); */
7163 /*     } else { */
7164 /*         tlbl = newiTempLabel(NULL); */
7165 /*         pic16_toBoolean(left);     */
7166 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7167 /*         pic16_toBoolean(right); */
7168 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7169 /*         pic16_outBitAcc(result); */
7170 /*     } */
7171
7172     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7173     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7174     pic16_freeAsmop(result,NULL,ic,TRUE);
7175 }
7176
7177
7178 /*-----------------------------------------------------------------*/
7179 /* genOrOp - for || operation                                      */
7180 /*-----------------------------------------------------------------*/
7181 /*
7182   tsd pic port -
7183   modified this code, but it doesn't appear to ever get called
7184 */
7185
7186 static void genOrOp (iCode *ic)
7187 {
7188     operand *left,*right, *result;
7189     symbol *tlbl;
7190
7191     /* note here that || operations that are in an
7192     if statement are taken away by backPatchLabels
7193     only those used in arthmetic operations remain */
7194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7195     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7196     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7197     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7198
7199     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7200
7201     /* if both are bit variables */
7202     if (AOP_TYPE(left) == AOP_CRY &&
7203         AOP_TYPE(right) == AOP_CRY ) {
7204       pic16_emitcode("clrc","");
7205       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7206                AOP(left)->aopu.aop_dir,
7207                AOP(left)->aopu.aop_dir);
7208       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7209                AOP(right)->aopu.aop_dir,
7210                AOP(right)->aopu.aop_dir);
7211       pic16_emitcode("setc","");
7212
7213     } else {
7214         tlbl = newiTempLabel(NULL);
7215         pic16_toBoolean(left);
7216         emitSKPZ;
7217         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7218         pic16_toBoolean(right);
7219         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7220
7221         pic16_outBitAcc(result);
7222     }
7223
7224     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226     pic16_freeAsmop(result,NULL,ic,TRUE);            
7227 }
7228
7229 /*-----------------------------------------------------------------*/
7230 /* isLiteralBit - test if lit == 2^n                               */
7231 /*-----------------------------------------------------------------*/
7232 static int isLiteralBit(unsigned long lit)
7233 {
7234     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7235     0x100L,0x200L,0x400L,0x800L,
7236     0x1000L,0x2000L,0x4000L,0x8000L,
7237     0x10000L,0x20000L,0x40000L,0x80000L,
7238     0x100000L,0x200000L,0x400000L,0x800000L,
7239     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7240     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7241     int idx;
7242     
7243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7244     for(idx = 0; idx < 32; idx++)
7245         if(lit == pw[idx])
7246             return idx+1;
7247     return 0;
7248 }
7249
7250 /*-----------------------------------------------------------------*/
7251 /* continueIfTrue -                                                */
7252 /*-----------------------------------------------------------------*/
7253 static void continueIfTrue (iCode *ic)
7254 {
7255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7256     if(IC_TRUE(ic))
7257         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7258     ic->generated = 1;
7259 }
7260
7261 /*-----------------------------------------------------------------*/
7262 /* jmpIfTrue -                                                     */
7263 /*-----------------------------------------------------------------*/
7264 static void jumpIfTrue (iCode *ic)
7265 {
7266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7267     if(!IC_TRUE(ic))
7268         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7269     ic->generated = 1;
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* jmpTrueOrFalse -                                                */
7274 /*-----------------------------------------------------------------*/
7275 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7276 {
7277     // ugly but optimized by peephole
7278     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7279     if(IC_TRUE(ic)){
7280         symbol *nlbl = newiTempLabel(NULL);
7281         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7282         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7283         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7284         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7285     }
7286     else{
7287         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7288         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7289     }
7290     ic->generated = 1;
7291 }
7292
7293 /*-----------------------------------------------------------------*/
7294 /* genAnd  - code for and                                          */
7295 /*-----------------------------------------------------------------*/
7296 static void genAnd (iCode *ic, iCode *ifx)
7297 {
7298   operand *left, *right, *result;
7299   int size, offset=0;  
7300   unsigned long lit = 0L;
7301   int bytelit = 0;
7302   resolvedIfx rIfx;
7303
7304
7305   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7306   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7307   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7308   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7309
7310   resolveIfx(&rIfx,ifx);
7311
7312   /* if left is a literal & right is not then exchange them */
7313   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7314       AOP_NEEDSACC(left)) {
7315     operand *tmp = right ;
7316     right = left;
7317     left = tmp;
7318   }
7319
7320   /* if result = right then exchange them */
7321   if(pic16_sameRegs(AOP(result),AOP(right))){
7322     operand *tmp = right ;
7323     right = left;
7324     left = tmp;
7325   }
7326
7327   /* if right is bit then exchange them */
7328   if (AOP_TYPE(right) == AOP_CRY &&
7329       AOP_TYPE(left) != AOP_CRY){
7330     operand *tmp = right ;
7331     right = left;
7332     left = tmp;
7333   }
7334   if(AOP_TYPE(right) == AOP_LIT)
7335     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7336
7337   size = AOP_SIZE(result);
7338
7339   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7340
7341   // if(bit & yy)
7342   // result = bit & yy;
7343   if (AOP_TYPE(left) == AOP_CRY){
7344     // c = bit & literal;
7345     if(AOP_TYPE(right) == AOP_LIT){
7346       if(lit & 1) {
7347         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7348           // no change
7349           goto release;
7350         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7351       } else {
7352         // bit(result) = 0;
7353         if(size && (AOP_TYPE(result) == AOP_CRY)){
7354           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7355           goto release;
7356         }
7357         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7358           jumpIfTrue(ifx);
7359           goto release;
7360         }
7361         pic16_emitcode("clr","c");
7362       }
7363     } else {
7364       if (AOP_TYPE(right) == AOP_CRY){
7365         // c = bit & bit;
7366         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7367         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7368       } else {
7369         // c = bit & val;
7370         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7371         // c = lsb
7372         pic16_emitcode("rrc","a");
7373         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7374       }
7375     }
7376     // bit = c
7377     // val = c
7378     if(size)
7379       pic16_outBitC(result);
7380     // if(bit & ...)
7381     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7382       genIfxJump(ifx, "c");           
7383     goto release ;
7384   }
7385
7386   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7387   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7388   if((AOP_TYPE(right) == AOP_LIT) &&
7389      (AOP_TYPE(result) == AOP_CRY) &&
7390      (AOP_TYPE(left) != AOP_CRY)){
7391     int posbit = isLiteralBit(lit);
7392     /* left &  2^n */
7393     if(posbit){
7394       posbit--;
7395       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7396       // bit = left & 2^n
7397       if(size)
7398         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7399       // if(left &  2^n)
7400       else{
7401         if(ifx){
7402 /*
7403           if(IC_TRUE(ifx)) {
7404             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7405             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7406           } else {
7407             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7408             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7409           }
7410 */
7411         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7412         size = AOP_SIZE(left);
7413
7414         {
7415           int bp = posbit, ofs=0;
7416           
7417             while(bp > 7) {
7418               bp -= 8;
7419               ofs++;
7420             }
7421         
7422           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7423                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7424
7425         }
7426 /*
7427           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7428                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7429 */
7430           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7431           
7432           ifx->generated = 1;
7433         }
7434         goto release;
7435       }
7436     } else {
7437       symbol *tlbl = newiTempLabel(NULL);
7438       int sizel = AOP_SIZE(left);
7439
7440       if(size)
7441         emitSETC;
7442
7443       while(sizel--) {
7444         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7445
7446           /* patch provided by Aaron Colwell */
7447           if((posbit = isLiteralBit(bytelit)) != 0) {
7448               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7449                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7450                                                 (posbit-1),0, PO_GPR_REGISTER));
7451
7452               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7453 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7454           } else {
7455               if (bytelit == 0xff) {
7456                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7457                    * a peephole could optimize it out -- VR */
7458                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7459               } else {
7460                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7461                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7462               }
7463
7464               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7465                             pic16_popGetLabel(tlbl->key));
7466           }
7467         
7468 #if 0
7469           /* old code, left here for reference -- VR 09/2004 */
7470           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7471           // byte ==  2^n ?
7472           if((posbit = isLiteralBit(bytelit)) != 0)
7473             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7474           else{
7475             if(bytelit != 0x0FFL)
7476               pic16_emitcode("anl","a,%s",
7477                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7478             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7479           }
7480 #endif
7481         }
7482         offset++;
7483       }
7484       // bit = left & literal
7485       if(size) {
7486         emitCLRC;
7487         pic16_emitpLabel(tlbl->key);
7488       }
7489       // if(left & literal)
7490       else {
7491         if(ifx) {
7492           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7493           pic16_emitpLabel(tlbl->key);
7494           ifx->generated = 1;
7495         }
7496         goto release;
7497       }
7498     }
7499
7500     pic16_outBitC(result);
7501     goto release ;
7502   }
7503
7504   /* if left is same as result */
7505   if(pic16_sameRegs(AOP(result),AOP(left))){
7506     int know_W = -1;
7507     for(;size--; offset++,lit>>=8) {
7508       if(AOP_TYPE(right) == AOP_LIT){
7509         switch(lit & 0xff) {
7510         case 0x00:
7511           /*  and'ing with 0 has clears the result */
7512 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7513           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7514           break;
7515         case 0xff:
7516           /* and'ing with 0xff is a nop when the result and left are the same */
7517           break;
7518
7519         default:
7520           {
7521             int p = my_powof2( (~lit) & 0xff );
7522             if(p>=0) {
7523               /* only one bit is set in the literal, so use a bcf instruction */
7524 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7525               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7526
7527             } else {
7528               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7529               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7530               if(know_W != (lit&0xff))
7531                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7532               know_W = lit &0xff;
7533               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7534             }
7535           }    
7536         }
7537       } else {
7538         if (AOP_TYPE(left) == AOP_ACC) {
7539           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7540         } else {                    
7541           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7542           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7543
7544         }
7545       }
7546     }
7547
7548   } else {
7549     // left & result in different registers
7550     if(AOP_TYPE(result) == AOP_CRY){
7551       // result = bit
7552       // if(size), result in bit
7553       // if(!size && ifx), conditional oper: if(left & right)
7554       symbol *tlbl = newiTempLabel(NULL);
7555       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7556       if(size)
7557         pic16_emitcode("setb","c");
7558       while(sizer--){
7559         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7560         pic16_emitcode("anl","a,%s",
7561                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7562         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7563         offset++;
7564       }
7565       if(size){
7566         CLRC;
7567         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7568         pic16_outBitC(result);
7569       } else if(ifx)
7570         jmpTrueOrFalse(ifx, tlbl);
7571     } else {
7572       for(;(size--);offset++) {
7573         // normal case
7574         // result = left & right
7575         if(AOP_TYPE(right) == AOP_LIT){
7576           int t = (lit >> (offset*8)) & 0x0FFL;
7577           switch(t) { 
7578           case 0x00:
7579             pic16_emitcode("clrf","%s",
7580                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7581             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7582             break;
7583           case 0xff:
7584             pic16_emitcode("movf","%s,w",
7585                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7586             pic16_emitcode("movwf","%s",
7587                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7588             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7589             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7590             break;
7591           default:
7592             pic16_emitcode("movlw","0x%x",t);
7593             pic16_emitcode("andwf","%s,w",
7594                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7595             pic16_emitcode("movwf","%s",
7596                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7597               
7598             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7599             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7600             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7601           }
7602           continue;
7603         }
7604
7605         if (AOP_TYPE(left) == AOP_ACC) {
7606           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7607           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7608         } else {
7609           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7610           pic16_emitcode("andwf","%s,w",
7611                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7612           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7613           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7614         }
7615         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7616         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7617       }
7618     }
7619   }
7620
7621   release :
7622     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7623   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7624   pic16_freeAsmop(result,NULL,ic,TRUE);     
7625 }
7626
7627 /*-----------------------------------------------------------------*/
7628 /* genOr  - code for or                                            */
7629 /*-----------------------------------------------------------------*/
7630 static void genOr (iCode *ic, iCode *ifx)
7631 {
7632     operand *left, *right, *result;
7633     int size, offset=0;
7634     unsigned long lit = 0L;
7635
7636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7637
7638     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7639     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7640     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7641
7642     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7643
7644     /* if left is a literal & right is not then exchange them */
7645     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7646         AOP_NEEDSACC(left)) {
7647         operand *tmp = right ;
7648         right = left;
7649         left = tmp;
7650     }
7651
7652     /* if result = right then exchange them */
7653     if(pic16_sameRegs(AOP(result),AOP(right))){
7654         operand *tmp = right ;
7655         right = left;
7656         left = tmp;
7657     }
7658
7659     /* if right is bit then exchange them */
7660     if (AOP_TYPE(right) == AOP_CRY &&
7661         AOP_TYPE(left) != AOP_CRY){
7662         operand *tmp = right ;
7663         right = left;
7664         left = tmp;
7665     }
7666
7667     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7668
7669     if(AOP_TYPE(right) == AOP_LIT)
7670         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7671
7672     size = AOP_SIZE(result);
7673
7674     // if(bit | yy)
7675     // xx = bit | yy;
7676     if (AOP_TYPE(left) == AOP_CRY){
7677         if(AOP_TYPE(right) == AOP_LIT){
7678             // c = bit & literal;
7679             if(lit){
7680                 // lit != 0 => result = 1
7681                 if(AOP_TYPE(result) == AOP_CRY){
7682                   if(size)
7683                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7684                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7685                   //     AOP(result)->aopu.aop_dir,
7686                   //     AOP(result)->aopu.aop_dir);
7687                     else if(ifx)
7688                         continueIfTrue(ifx);
7689                     goto release;
7690                 }
7691             } else {
7692                 // lit == 0 => result = left
7693                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7694                     goto release;
7695                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7696             }
7697         } else {
7698             if (AOP_TYPE(right) == AOP_CRY){
7699               if(pic16_sameRegs(AOP(result),AOP(left))){
7700                 // c = bit | bit;
7701                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7702                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7703                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7704
7705                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7706                          AOP(result)->aopu.aop_dir,
7707                          AOP(result)->aopu.aop_dir);
7708                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7709                          AOP(right)->aopu.aop_dir,
7710                          AOP(right)->aopu.aop_dir);
7711                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7712                          AOP(result)->aopu.aop_dir,
7713                          AOP(result)->aopu.aop_dir);
7714               } else {
7715                 if( AOP_TYPE(result) == AOP_ACC) {
7716                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7717                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7718                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7719                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7720
7721                 } else {
7722
7723                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7724                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7725                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7726                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7727
7728                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7729                                  AOP(result)->aopu.aop_dir,
7730                                  AOP(result)->aopu.aop_dir);
7731                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7732                                  AOP(right)->aopu.aop_dir,
7733                                  AOP(right)->aopu.aop_dir);
7734                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7735                                  AOP(left)->aopu.aop_dir,
7736                                  AOP(left)->aopu.aop_dir);
7737                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7738                                  AOP(result)->aopu.aop_dir,
7739                                  AOP(result)->aopu.aop_dir);
7740                 }
7741               }
7742             } else {
7743                 // c = bit | val;
7744                 symbol *tlbl = newiTempLabel(NULL);
7745                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7746
7747
7748                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7749                 if( AOP_TYPE(right) == AOP_ACC) {
7750                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7751                   emitSKPNZ;
7752                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7753                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7754                 }
7755
7756
7757
7758                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7759                     pic16_emitcode(";XXX setb","c");
7760                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7761                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7762                 pic16_toBoolean(right);
7763                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7764                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7765                     jmpTrueOrFalse(ifx, tlbl);
7766                     goto release;
7767                 } else {
7768                     CLRC;
7769                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7770                 }
7771             }
7772         }
7773         // bit = c
7774         // val = c
7775         if(size)
7776             pic16_outBitC(result);
7777         // if(bit | ...)
7778         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7779             genIfxJump(ifx, "c");           
7780         goto release ;
7781     }
7782
7783     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7784     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7785     if((AOP_TYPE(right) == AOP_LIT) &&
7786        (AOP_TYPE(result) == AOP_CRY) &&
7787        (AOP_TYPE(left) != AOP_CRY)){
7788         if(lit){
7789           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7790             // result = 1
7791             if(size)
7792                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7793             else 
7794                 continueIfTrue(ifx);
7795             goto release;
7796         } else {
7797           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7798             // lit = 0, result = boolean(left)
7799             if(size)
7800                 pic16_emitcode(";XXX setb","c");
7801             pic16_toBoolean(right);
7802             if(size){
7803                 symbol *tlbl = newiTempLabel(NULL);
7804                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7805                 CLRC;
7806                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7807             } else {
7808                 genIfxJump (ifx,"a");
7809                 goto release;
7810             }
7811         }
7812         pic16_outBitC(result);
7813         goto release ;
7814     }
7815
7816     /* if left is same as result */
7817     if(pic16_sameRegs(AOP(result),AOP(left))){
7818       int know_W = -1;
7819       for(;size--; offset++,lit>>=8) {
7820         if(AOP_TYPE(right) == AOP_LIT){
7821           if((lit & 0xff) == 0)
7822             /*  or'ing with 0 has no effect */
7823             continue;
7824           else {
7825             int p = my_powof2(lit & 0xff);
7826             if(p>=0) {
7827               /* only one bit is set in the literal, so use a bsf instruction */
7828               pic16_emitpcode(POC_BSF,
7829                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7830             } else {
7831               if(know_W != (lit & 0xff))
7832                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7833               know_W = lit & 0xff;
7834               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7835             }
7836                     
7837           }
7838         } else {
7839           if (AOP_TYPE(left) == AOP_ACC) {
7840             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7841             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7842           } else {                  
7843             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7844             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7845
7846             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7847             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848
7849           }
7850         }
7851       }
7852     } else {
7853         // left & result in different registers
7854         if(AOP_TYPE(result) == AOP_CRY){
7855             // result = bit
7856             // if(size), result in bit
7857             // if(!size && ifx), conditional oper: if(left | right)
7858             symbol *tlbl = newiTempLabel(NULL);
7859             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7860             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7861
7862
7863             if(size)
7864                 pic16_emitcode(";XXX setb","c");
7865             while(sizer--){
7866                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7867                 pic16_emitcode(";XXX orl","a,%s",
7868                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7869                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7870                 offset++;
7871             }
7872             if(size){
7873                 CLRC;
7874                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7875                 pic16_outBitC(result);
7876             } else if(ifx)
7877                 jmpTrueOrFalse(ifx, tlbl);
7878         } else for(;(size--);offset++){
7879           // normal case
7880           // result = left & right
7881           if(AOP_TYPE(right) == AOP_LIT){
7882             int t = (lit >> (offset*8)) & 0x0FFL;
7883             switch(t) { 
7884             case 0x00:
7885               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7886               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7887
7888               pic16_emitcode("movf","%s,w",
7889                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890               pic16_emitcode("movwf","%s",
7891                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7892               break;
7893             default:
7894               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7895               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7896               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7897
7898               pic16_emitcode("movlw","0x%x",t);
7899               pic16_emitcode("iorwf","%s,w",
7900                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7901               pic16_emitcode("movwf","%s",
7902                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7903               
7904             }
7905             continue;
7906           }
7907
7908           // faster than result <- left, anl result,right
7909           // and better if result is SFR
7910           if (AOP_TYPE(left) == AOP_ACC) {
7911             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7912             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7913           } else {
7914             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7915             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7916
7917             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918             pic16_emitcode("iorwf","%s,w",
7919                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920           }
7921           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7922           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7923         }
7924     }
7925
7926 release :
7927     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7928     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7929     pic16_freeAsmop(result,NULL,ic,TRUE);     
7930 }
7931
7932 /*-----------------------------------------------------------------*/
7933 /* genXor - code for xclusive or                                   */
7934 /*-----------------------------------------------------------------*/
7935 static void genXor (iCode *ic, iCode *ifx)
7936 {
7937   operand *left, *right, *result;
7938   int size, offset=0;
7939   unsigned long lit = 0L;
7940
7941   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7942
7943   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7944   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7945   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7946
7947   /* if left is a literal & right is not ||
7948      if left needs acc & right does not */
7949   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7950       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7951     operand *tmp = right ;
7952     right = left;
7953     left = tmp;
7954   }
7955
7956   /* if result = right then exchange them */
7957   if(pic16_sameRegs(AOP(result),AOP(right))){
7958     operand *tmp = right ;
7959     right = left;
7960     left = tmp;
7961   }
7962
7963   /* if right is bit then exchange them */
7964   if (AOP_TYPE(right) == AOP_CRY &&
7965       AOP_TYPE(left) != AOP_CRY){
7966     operand *tmp = right ;
7967     right = left;
7968     left = tmp;
7969   }
7970   if(AOP_TYPE(right) == AOP_LIT)
7971     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7972
7973   size = AOP_SIZE(result);
7974
7975   // if(bit ^ yy)
7976   // xx = bit ^ yy;
7977   if (AOP_TYPE(left) == AOP_CRY){
7978     if(AOP_TYPE(right) == AOP_LIT){
7979       // c = bit & literal;
7980       if(lit>>1){
7981         // lit>>1  != 0 => result = 1
7982         if(AOP_TYPE(result) == AOP_CRY){
7983           if(size)
7984             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7985             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7986           else if(ifx)
7987             continueIfTrue(ifx);
7988           goto release;
7989         }
7990         pic16_emitcode("setb","c");
7991       } else{
7992         // lit == (0 or 1)
7993         if(lit == 0){
7994           // lit == 0, result = left
7995           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7996             goto release;
7997           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7998         } else{
7999           // lit == 1, result = not(left)
8000           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8001             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8002             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8003             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8004             goto release;
8005           } else {
8006             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8007             pic16_emitcode("cpl","c");
8008           }
8009         }
8010       }
8011
8012     } else {
8013       // right != literal
8014       symbol *tlbl = newiTempLabel(NULL);
8015       if (AOP_TYPE(right) == AOP_CRY){
8016         // c = bit ^ bit;
8017         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8018       }
8019       else{
8020         int sizer = AOP_SIZE(right);
8021         // c = bit ^ val
8022         // if val>>1 != 0, result = 1
8023         pic16_emitcode("setb","c");
8024         while(sizer){
8025           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8026           if(sizer == 1)
8027             // test the msb of the lsb
8028             pic16_emitcode("anl","a,#0xfe");
8029           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8030           sizer--;
8031         }
8032         // val = (0,1)
8033         pic16_emitcode("rrc","a");
8034       }
8035       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8036       pic16_emitcode("cpl","c");
8037       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8038     }
8039     // bit = c
8040     // val = c
8041     if(size)
8042       pic16_outBitC(result);
8043     // if(bit | ...)
8044     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8045       genIfxJump(ifx, "c");           
8046     goto release ;
8047   }
8048
8049   if(pic16_sameRegs(AOP(result),AOP(left))){
8050     /* if left is same as result */
8051     for(;size--; offset++) {
8052       if(AOP_TYPE(right) == AOP_LIT){
8053         int t  = (lit >> (offset*8)) & 0x0FFL;
8054         if(t == 0x00L)
8055           continue;
8056         else
8057           if (IS_AOP_PREG(left)) {
8058             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8060             pic16_aopPut(AOP(result),"a",offset);
8061           } else {
8062             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8063             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8064             pic16_emitcode("xrl","%s,%s",
8065                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8066                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8067           }
8068       } else {
8069         if (AOP_TYPE(left) == AOP_ACC)
8070           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8071         else {
8072           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8073           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8074 /*
8075           if (IS_AOP_PREG(left)) {
8076             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8077             pic16_aopPut(AOP(result),"a",offset);
8078           } else
8079             pic16_emitcode("xrl","%s,a",
8080                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8081 */
8082         }
8083       }
8084     }
8085   } else {
8086     // left & result in different registers
8087     if(AOP_TYPE(result) == AOP_CRY){
8088       // result = bit
8089       // if(size), result in bit
8090       // if(!size && ifx), conditional oper: if(left ^ right)
8091       symbol *tlbl = newiTempLabel(NULL);
8092       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8093       if(size)
8094         pic16_emitcode("setb","c");
8095       while(sizer--){
8096         if((AOP_TYPE(right) == AOP_LIT) &&
8097            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8098           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8099         } else {
8100           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8101           pic16_emitcode("xrl","a,%s",
8102                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8103         }
8104         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8105         offset++;
8106       }
8107       if(size){
8108         CLRC;
8109         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8110         pic16_outBitC(result);
8111       } else if(ifx)
8112         jmpTrueOrFalse(ifx, tlbl);
8113     } else for(;(size--);offset++){
8114       // normal case
8115       // result = left & right
8116       if(AOP_TYPE(right) == AOP_LIT){
8117         int t = (lit >> (offset*8)) & 0x0FFL;
8118         switch(t) { 
8119         case 0x00:
8120           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8121           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8122           pic16_emitcode("movf","%s,w",
8123                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8124           pic16_emitcode("movwf","%s",
8125                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8126           break;
8127         case 0xff:
8128           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8129           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8130           pic16_emitcode("comf","%s,w",
8131                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8132           pic16_emitcode("movwf","%s",
8133                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8134           break;
8135         default:
8136           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8137           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8138           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8139           pic16_emitcode("movlw","0x%x",t);
8140           pic16_emitcode("xorwf","%s,w",
8141                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8142           pic16_emitcode("movwf","%s",
8143                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8144
8145         }
8146         continue;
8147       }
8148
8149       // faster than result <- left, anl result,right
8150       // and better if result is SFR
8151       if (AOP_TYPE(left) == AOP_ACC) {
8152         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8153         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154       } else {
8155         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8156         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8157         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159       }
8160       if ( AOP_TYPE(result) != AOP_ACC){
8161         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8162         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8163       }
8164     }
8165   }
8166
8167   release :
8168     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8169   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8170   pic16_freeAsmop(result,NULL,ic,TRUE);     
8171 }
8172
8173 /*-----------------------------------------------------------------*/
8174 /* genInline - write the inline code out                           */
8175 /*-----------------------------------------------------------------*/
8176 static void genInline (iCode *ic)
8177 {
8178   char *buffer, *bp, *bp1;
8179     
8180         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8181
8182         _G.inLine += (!options.asmpeep);
8183
8184         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8185         strcpy(buffer,IC_INLINE(ic));
8186
8187 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8188
8189         /* emit each line as a code */
8190         while (*bp) {
8191                 if (*bp == '\n') {
8192                         *bp++ = '\0';
8193
8194                         if(*bp1)
8195                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8196                         bp1 = bp;
8197                 } else {
8198                         if (*bp == ':') {
8199                                 bp++;
8200                                 *bp = '\0';
8201                                 bp++;
8202
8203                                 /* print label, use this special format with NULL directive
8204                                  * to denote that the argument should not be indented with tab */
8205                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8206                                 bp1 = bp;
8207                         } else
8208                                 bp++;
8209                 }
8210         }
8211
8212         if ((bp1 != bp) && *bp1)
8213                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8214
8215
8216     Safe_free(buffer);
8217
8218     _G.inLine -= (!options.asmpeep);
8219 }
8220
8221 /*-----------------------------------------------------------------*/
8222 /* genRRC - rotate right with carry                                */
8223 /*-----------------------------------------------------------------*/
8224 static void genRRC (iCode *ic)
8225 {
8226   operand *left , *result ;
8227   int size, offset = 0, same;
8228
8229   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8230
8231   /* rotate right with carry */
8232   left = IC_LEFT(ic);
8233   result=IC_RESULT(ic);
8234   pic16_aopOp (left,ic,FALSE);
8235   pic16_aopOp (result,ic,FALSE);
8236
8237   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8238
8239   same = pic16_sameRegs(AOP(result),AOP(left));
8240
8241   size = AOP_SIZE(result);    
8242
8243   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8244
8245   /* get the lsb and put it into the carry */
8246   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8247
8248   offset = 0 ;
8249
8250   while(size--) {
8251
8252     if(same) {
8253       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8254     } else {
8255       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8256       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8257     }
8258
8259     offset++;
8260   }
8261
8262   pic16_freeAsmop(left,NULL,ic,TRUE);
8263   pic16_freeAsmop(result,NULL,ic,TRUE);
8264 }
8265
8266 /*-----------------------------------------------------------------*/
8267 /* genRLC - generate code for rotate left with carry               */
8268 /*-----------------------------------------------------------------*/
8269 static void genRLC (iCode *ic)
8270 {    
8271   operand *left , *result ;
8272   int size, offset = 0;
8273   int same;
8274
8275   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8276   /* rotate right with carry */
8277   left = IC_LEFT(ic);
8278   result=IC_RESULT(ic);
8279   pic16_aopOp (left,ic,FALSE);
8280   pic16_aopOp (result,ic,FALSE);
8281
8282   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8283
8284   same = pic16_sameRegs(AOP(result),AOP(left));
8285
8286   /* move it to the result */
8287   size = AOP_SIZE(result);    
8288
8289   /* get the msb and put it into the carry */
8290   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8291
8292   offset = 0 ;
8293
8294   while(size--) {
8295
8296     if(same) {
8297       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8298     } else {
8299       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8300       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8301     }
8302
8303     offset++;
8304   }
8305
8306
8307   pic16_freeAsmop(left,NULL,ic,TRUE);
8308   pic16_freeAsmop(result,NULL,ic,TRUE);
8309 }
8310
8311
8312 /* gpasm can get the highest order bit with HIGH/UPPER
8313  * so the following probably is not needed -- VR */
8314  
8315 /*-----------------------------------------------------------------*/
8316 /* genGetHbit - generates code get highest order bit               */
8317 /*-----------------------------------------------------------------*/
8318 static void genGetHbit (iCode *ic)
8319 {
8320     operand *left, *result;
8321     left = IC_LEFT(ic);
8322     result=IC_RESULT(ic);
8323     pic16_aopOp (left,ic,FALSE);
8324     pic16_aopOp (result,ic,FALSE);
8325
8326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8327     /* get the highest order byte into a */
8328     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8329     if(AOP_TYPE(result) == AOP_CRY){
8330         pic16_emitcode("rlc","a");
8331         pic16_outBitC(result);
8332     }
8333     else{
8334         pic16_emitcode("rl","a");
8335         pic16_emitcode("anl","a,#0x01");
8336         pic16_outAcc(result);
8337     }
8338
8339
8340     pic16_freeAsmop(left,NULL,ic,TRUE);
8341     pic16_freeAsmop(result,NULL,ic,TRUE);
8342 }
8343
8344 #if 0
8345 /*-----------------------------------------------------------------*/
8346 /* AccRol - rotate left accumulator by known count                 */
8347 /*-----------------------------------------------------------------*/
8348 static void AccRol (int shCount)
8349 {
8350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8351     shCount &= 0x0007;              // shCount : 0..7
8352     switch(shCount){
8353         case 0 :
8354             break;
8355         case 1 :
8356             pic16_emitcode("rl","a");
8357             break;
8358         case 2 :
8359             pic16_emitcode("rl","a");
8360             pic16_emitcode("rl","a");
8361             break;
8362         case 3 :
8363             pic16_emitcode("swap","a");
8364             pic16_emitcode("rr","a");
8365             break;
8366         case 4 :
8367             pic16_emitcode("swap","a");
8368             break;
8369         case 5 :
8370             pic16_emitcode("swap","a");
8371             pic16_emitcode("rl","a");
8372             break;
8373         case 6 :
8374             pic16_emitcode("rr","a");
8375             pic16_emitcode("rr","a");
8376             break;
8377         case 7 :
8378             pic16_emitcode("rr","a");
8379             break;
8380     }
8381 }
8382 #endif
8383
8384 /*-----------------------------------------------------------------*/
8385 /* AccLsh - left shift accumulator by known count                  */
8386 /*-----------------------------------------------------------------*/
8387 static void AccLsh (int shCount)
8388 {
8389         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8390         switch(shCount){
8391                 case 0 :
8392                         return;
8393                         break;
8394                 case 1 :
8395                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8396                         break;
8397                 case 2 :
8398                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8399                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8400                         break;
8401                 case 3 :
8402                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8403                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8404                         break;
8405                 case 4 :
8406                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8407                         break;
8408                 case 5 :
8409                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8410                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8411                         break;
8412                 case 6 :
8413                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8414                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8415                         break;
8416                 case 7 :
8417                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8418                         break;
8419         }
8420
8421         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8422 }
8423
8424 /*-----------------------------------------------------------------*/
8425 /* AccRsh - right shift accumulator by known count                 */
8426 /*-----------------------------------------------------------------*/
8427 static void AccRsh (int shCount, int andmask)
8428 {
8429         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8430         switch(shCount){
8431                 case 0 :
8432                         return; break;
8433                 case 1 :
8434                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8435                         break;
8436                 case 2 :
8437                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8438                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8439                         break;
8440                 case 3 :
8441                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8442                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8443                         break;
8444                 case 4 :
8445                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8446                         break;
8447                 case 5 :
8448                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8450                         break;
8451                 case 6 :
8452                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8453                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8454                         break;
8455                 case 7 :
8456                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8457                         break;
8458         }
8459         
8460         if(andmask)
8461                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8462         else
8463                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8464 }
8465
8466 #if 0
8467 /*-----------------------------------------------------------------*/
8468 /* AccSRsh - signed right shift accumulator by known count                 */
8469 /*-----------------------------------------------------------------*/
8470 static void AccSRsh (int shCount)
8471 {
8472     symbol *tlbl ;
8473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8474     if(shCount != 0){
8475         if(shCount == 1){
8476             pic16_emitcode("mov","c,acc.7");
8477             pic16_emitcode("rrc","a");
8478         } else if(shCount == 2){
8479             pic16_emitcode("mov","c,acc.7");
8480             pic16_emitcode("rrc","a");
8481             pic16_emitcode("mov","c,acc.7");
8482             pic16_emitcode("rrc","a");
8483         } else {
8484             tlbl = newiTempLabel(NULL);
8485             /* rotate right accumulator */
8486             AccRol(8 - shCount);
8487             /* and kill the higher order bits */
8488             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8489             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8490             pic16_emitcode("orl","a,#0x%02x",
8491                      (unsigned char)~SRMask[shCount]);
8492             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8493         }
8494     }
8495 }
8496 #endif
8497
8498 /*-----------------------------------------------------------------*/
8499 /* shiftR1Left2Result - shift right one byte from left to result   */
8500 /*-----------------------------------------------------------------*/
8501 static void shiftR1Left2ResultSigned (operand *left, int offl,
8502                                 operand *result, int offr,
8503                                 int shCount)
8504 {
8505   int same;
8506
8507   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8508
8509   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8510
8511   switch(shCount) {
8512   case 1:
8513     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8514     if(same) 
8515       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8516     else {
8517       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8518       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8519     }
8520
8521     break;
8522   case 2:
8523
8524     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8525     if(same) 
8526       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8527     else {
8528       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8529       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8530     }
8531     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8532     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8533
8534     break;
8535
8536   case 3:
8537     if(same)
8538       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8539     else {
8540       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8541       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8542     }
8543
8544     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8545     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8546     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8547
8548     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8549     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8550
8551     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8552     break;
8553
8554   case 4:
8555     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8556     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8557     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8558     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8559     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8560     break;
8561   case 5:
8562     if(same) {
8563       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8564     } else {
8565       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8566       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8567     }
8568     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8569     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8570     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8571     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8572     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8573     break;
8574
8575   case 6:
8576     if(same) {
8577       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8578       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8579       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8580       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8581       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8582       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8583     } else {
8584       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8585       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8586       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8587       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8588       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8589     }
8590     break;
8591
8592   case 7:
8593     if(same) {
8594       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8595       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8596       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8597       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8598     } else {
8599       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8600       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8601       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8602     }
8603
8604   default:
8605     break;
8606   }
8607 }
8608
8609 /*-----------------------------------------------------------------*/
8610 /* shiftR1Left2Result - shift right one byte from left to result   */
8611 /*-----------------------------------------------------------------*/
8612 static void shiftR1Left2Result (operand *left, int offl,
8613                                 operand *result, int offr,
8614                                 int shCount, int sign)
8615 {
8616   int same;
8617
8618   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8619
8620   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8621
8622   /* Copy the msb into the carry if signed. */
8623   if(sign) {
8624     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8625     return;
8626   }
8627
8628
8629
8630   switch(shCount) {
8631   case 1:
8632     emitCLRC;
8633     if(same) 
8634       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8635     else {
8636       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8637       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8638     }
8639     break;
8640   case 2:
8641     emitCLRC;
8642     if(same) {
8643       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8644     } else {
8645       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8646       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8647     }
8648     emitCLRC;
8649     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8650
8651     break;
8652   case 3:
8653     if(same)
8654       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8655     else {
8656       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8657       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658     }
8659
8660     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8661     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8662     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8663     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8664     break;
8665       
8666   case 4:
8667     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8669     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8670     break;
8671
8672   case 5:
8673     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8675     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8676     //emitCLRC;
8677     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8678
8679     break;
8680   case 6:
8681
8682     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8683     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8684     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8685     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8686     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8687     break;
8688
8689   case 7:
8690
8691     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8692     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8693     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8694
8695     break;
8696
8697   default:
8698     break;
8699   }
8700 }
8701
8702 /*-----------------------------------------------------------------*/
8703 /* shiftL1Left2Result - shift left one byte from left to result    */
8704 /*-----------------------------------------------------------------*/
8705 static void shiftL1Left2Result (operand *left, int offl,
8706                                 operand *result, int offr, int shCount)
8707 {
8708   int same;
8709
8710   //    char *l;
8711   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8712
8713   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8714   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8715     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8716     //    MOVA(l);
8717     /* shift left accumulator */
8718     //AccLsh(shCount); // don't comment out just yet...
8719   //    pic16_aopPut(AOP(result),"a",offr);
8720
8721   switch(shCount) {
8722   case 1:
8723     /* Shift left 1 bit position */
8724     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8725     if(same) {
8726       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8727     } else {
8728       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8729       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8730     }
8731     break;
8732   case 2:
8733     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8734     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8735     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8736     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8737     break;
8738   case 3:
8739     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8740     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8741     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8742     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8743     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8744     break;
8745   case 4:
8746     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8747     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8748     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8749     break;
8750   case 5:
8751     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8752     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8753     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8754     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8755     break;
8756   case 6:
8757     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8758     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8759     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8760     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8761     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8762     break;
8763   case 7:
8764     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8765     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8766     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8767     break;
8768
8769   default:
8770     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8771   }
8772
8773 }
8774
8775 /*-----------------------------------------------------------------*/
8776 /* movLeft2Result - move byte from left to result                  */
8777 /*-----------------------------------------------------------------*/
8778 static void movLeft2Result (operand *left, int offl,
8779                             operand *result, int offr)
8780 {
8781   char *l;
8782   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8783   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8784     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8785
8786     if (*l == '@' && (IS_AOP_PREG(result))) {
8787       pic16_emitcode("mov","a,%s",l);
8788       pic16_aopPut(AOP(result),"a",offr);
8789     } else {
8790       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8791       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8792     }
8793   }
8794 }
8795
8796 /*-----------------------------------------------------------------*/
8797 /* shiftL2Left2Result - shift left two bytes from left to result   */
8798 /*-----------------------------------------------------------------*/
8799 static void shiftL2Left2Result (operand *left, int offl,
8800                                 operand *result, int offr, int shCount)
8801 {
8802   int same = pic16_sameRegs(AOP(result), AOP(left));
8803   int i;
8804
8805   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8806
8807   if (same && (offl != offr)) { // shift bytes
8808     if (offr > offl) {
8809        for(i=1;i>-1;i--) {
8810          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8811          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8812        }
8813     } else { // just treat as different later on
8814                 same = 0;
8815     }
8816   }
8817
8818   if(same) {
8819     switch(shCount) {
8820     case 0:
8821       break;
8822     case 1:
8823     case 2:
8824     case 3:
8825
8826       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8827       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8828       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8829
8830       while(--shCount) {
8831                 emitCLRC;
8832                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8833                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8834       }
8835
8836       break;
8837     case 4:
8838     case 5:
8839       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8840       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8841       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8842       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8843       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8844       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8845       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8846       if(shCount >=5) {
8847                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8848                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8849       }
8850       break;
8851     case 6:
8852       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8853       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8854       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8855       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8856       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8857       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8858       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8859       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8860       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8861       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8862       break;
8863     case 7:
8864       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8865       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8866       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8867       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8868       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8869     }
8870
8871   } else {
8872     switch(shCount) {
8873     case 0:
8874       break;
8875     case 1:
8876     case 2:
8877     case 3:
8878       /* note, use a mov/add for the shift since the mov has a
8879          chance of getting optimized out */
8880       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8881       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8882       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8883       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8884       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8885
8886       while(--shCount) {
8887                 emitCLRC;
8888                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8889                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8890       }
8891       break;
8892
8893     case 4:
8894     case 5:
8895       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8896       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8898       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8899       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8900       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8901       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8902       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8903
8904
8905       if(shCount == 5) {
8906                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8907                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8908       }
8909       break;
8910     case 6:
8911       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8912       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8913       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8914       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8915
8916       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8917       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8918       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8919       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8920       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8921       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8922       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8923       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8924       break;
8925     case 7:
8926       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8927       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8928       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8929       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8930       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8931     }
8932   }
8933
8934 }
8935 /*-----------------------------------------------------------------*/
8936 /* shiftR2Left2Result - shift right two bytes from left to result  */
8937 /*-----------------------------------------------------------------*/
8938 static void shiftR2Left2Result (operand *left, int offl,
8939                                 operand *result, int offr,
8940                                 int shCount, int sign)
8941 {
8942   int same = pic16_sameRegs(AOP(result), AOP(left));
8943   int i;
8944   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8945
8946   if (same && (offl != offr)) { // shift right bytes
8947     if (offr < offl) {
8948        for(i=0;i<2;i++) {
8949          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8950          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8951        }
8952     } else { // just treat as different later on
8953                 same = 0;
8954     }
8955   }
8956
8957   switch(shCount) {
8958   case 0:
8959     break;
8960   case 1:
8961   case 2:
8962   case 3:
8963     if(sign)
8964       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8965     else
8966       emitCLRC;
8967
8968     if(same) {
8969       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8970       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8971     } else {
8972       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8973       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8976     }
8977
8978     while(--shCount) {
8979       if(sign)
8980                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8981       else
8982                 emitCLRC;
8983       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8984       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8985     }
8986     break;
8987   case 4:
8988   case 5:
8989     if(same) {
8990
8991       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8992       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8994
8995       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8996       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8997       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8998       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8999     } else {
9000       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9001       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9002       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9003
9004       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9005       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9006       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9007       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9008       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9009     }
9010
9011     if(shCount >=5) {
9012       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9013       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9014     }
9015
9016     if(sign) {
9017       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9018       pic16_emitpcode(POC_BTFSC, 
9019                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9021     }
9022
9023     break;
9024
9025   case 6:
9026     if(same) {
9027
9028       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9030
9031       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9032       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9033       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9034       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9035       if(sign) {
9036         pic16_emitpcode(POC_BTFSC, 
9037                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9038         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9039       }
9040       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9041       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9042       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9044     } else {
9045       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9046       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9048       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9050       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9051       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9052       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9053       if(sign) {
9054         pic16_emitpcode(POC_BTFSC, 
9055                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9056         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9057       }
9058       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9059       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9060
9061         
9062     }
9063
9064     break;
9065   case 7:
9066     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9067     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9068     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9069     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9070     if(sign) {
9071       emitSKPNC;
9072       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9073     } else 
9074       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9075   }
9076 }
9077
9078
9079 /*-----------------------------------------------------------------*/
9080 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9081 /*-----------------------------------------------------------------*/
9082 static void shiftLLeftOrResult (operand *left, int offl,
9083                                 operand *result, int offr, int shCount)
9084 {
9085     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9086
9087     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9088     /* shift left accumulator */
9089     AccLsh(shCount);
9090     /* or with result */
9091     /* back to result */
9092     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9093 }
9094
9095 /*-----------------------------------------------------------------*/
9096 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9097 /*-----------------------------------------------------------------*/
9098 static void shiftRLeftOrResult (operand *left, int offl,
9099                                 operand *result, int offr, int shCount)
9100 {
9101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9102     
9103     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9104     /* shift right accumulator */
9105     AccRsh(shCount, 1);
9106     /* or with result */
9107     /* back to result */
9108     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9109 }
9110
9111 /*-----------------------------------------------------------------*/
9112 /* genlshOne - left shift a one byte quantity by known count       */
9113 /*-----------------------------------------------------------------*/
9114 static void genlshOne (operand *result, operand *left, int shCount)
9115 {       
9116     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9117     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9118 }
9119
9120 /*-----------------------------------------------------------------*/
9121 /* genlshTwo - left shift two bytes by known amount != 0           */
9122 /*-----------------------------------------------------------------*/
9123 static void genlshTwo (operand *result,operand *left, int shCount)
9124 {
9125     int size;
9126     
9127     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9128     size = pic16_getDataSize(result);
9129
9130     /* if shCount >= 8 */
9131     if (shCount >= 8) {
9132         shCount -= 8 ;
9133
9134         if (size > 1){
9135             if (shCount)
9136                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9137             else 
9138                 movLeft2Result(left, LSB, result, MSB16);
9139         }
9140         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9141     }
9142
9143     /*  1 <= shCount <= 7 */
9144     else {  
9145         if(size == 1)
9146             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9147         else 
9148             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9149     }
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* shiftLLong - shift left one long from left to result            */
9154 /* offr = LSB or MSB16                                             */
9155 /*-----------------------------------------------------------------*/
9156 static void shiftLLong (operand *left, operand *result, int offr )
9157 {
9158     int size = AOP_SIZE(result);
9159     int same = pic16_sameRegs(AOP(left),AOP(result));
9160         int i;
9161
9162     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9163
9164         if (same && (offr == MSB16)) { //shift one byte
9165                 for(i=size-1;i>=MSB16;i--) {
9166                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9167                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9168                 }
9169         } else {
9170                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9171         }
9172         
9173     if (size > LSB+offr ){
9174                 if (same) {
9175                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9176                 } else {
9177                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9178                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9179                 }
9180          }
9181
9182     if(size > MSB16+offr){
9183                 if (same) {
9184                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9185                 } else {
9186                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9187                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9188                 }
9189     }
9190
9191     if(size > MSB24+offr){
9192                 if (same) {
9193                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9194                 } else {
9195                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9196                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9197                 }
9198     }
9199
9200     if(size > MSB32+offr){
9201                 if (same) {
9202                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9203                 } else {
9204                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9205                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9206                 }
9207     }
9208     if(offr != LSB)
9209                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9210
9211 }
9212
9213 /*-----------------------------------------------------------------*/
9214 /* genlshFour - shift four byte by a known amount != 0             */
9215 /*-----------------------------------------------------------------*/
9216 static void genlshFour (operand *result, operand *left, int shCount)
9217 {
9218     int size;
9219
9220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9221     size = AOP_SIZE(result);
9222
9223     /* if shifting more that 3 bytes */
9224     if (shCount >= 24 ) {
9225         shCount -= 24;
9226         if (shCount)
9227             /* lowest order of left goes to the highest
9228             order of the destination */
9229             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9230         else
9231             movLeft2Result(left, LSB, result, MSB32);
9232
9233                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9234                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9235                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9236
9237         return;
9238     }
9239
9240     /* more than two bytes */
9241     else if ( shCount >= 16 ) {
9242         /* lower order two bytes goes to higher order two bytes */
9243         shCount -= 16;
9244         /* if some more remaining */
9245         if (shCount)
9246             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9247         else {
9248             movLeft2Result(left, MSB16, result, MSB32);
9249             movLeft2Result(left, LSB, result, MSB24);
9250         }
9251                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9252                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9253         return;
9254     }    
9255
9256     /* if more than 1 byte */
9257     else if ( shCount >= 8 ) {
9258         /* lower order three bytes goes to higher order  three bytes */
9259         shCount -= 8;
9260         if(size == 2){
9261             if(shCount)
9262                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9263             else
9264                 movLeft2Result(left, LSB, result, MSB16);
9265         }
9266         else{   /* size = 4 */
9267             if(shCount == 0){
9268                 movLeft2Result(left, MSB24, result, MSB32);
9269                 movLeft2Result(left, MSB16, result, MSB24);
9270                 movLeft2Result(left, LSB, result, MSB16);
9271                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9272             }
9273             else if(shCount == 1)
9274                 shiftLLong(left, result, MSB16);
9275             else{
9276                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9277                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9278                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9279                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9280             }
9281         }
9282     }
9283
9284     /* 1 <= shCount <= 7 */
9285     else if(shCount <= 3)
9286     { 
9287         shiftLLong(left, result, LSB);
9288         while(--shCount >= 1)
9289             shiftLLong(result, result, LSB);
9290     }
9291     /* 3 <= shCount <= 7, optimize */
9292     else{
9293         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9294         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9295         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9296     }
9297 }
9298
9299 /*-----------------------------------------------------------------*/
9300 /* genLeftShiftLiteral - left shifting by known count              */
9301 /*-----------------------------------------------------------------*/
9302 static void genLeftShiftLiteral (operand *left,
9303                                  operand *right,
9304                                  operand *result,
9305                                  iCode *ic)
9306 {    
9307     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9308     int size;
9309
9310     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9311     pic16_freeAsmop(right,NULL,ic,TRUE);
9312
9313     pic16_aopOp(left,ic,FALSE);
9314     pic16_aopOp(result,ic,FALSE);
9315
9316     size = getSize(operandType(result));
9317
9318 #if VIEW_SIZE
9319     pic16_emitcode("; shift left ","result %d, left %d",size,
9320              AOP_SIZE(left));
9321 #endif
9322
9323     /* I suppose that the left size >= result size */
9324     if(shCount == 0){
9325         while(size--){
9326             movLeft2Result(left, size, result, size);
9327         }
9328     }
9329
9330     else if(shCount >= (size * 8))
9331         while(size--)
9332             pic16_aopPut(AOP(result),zero,size);
9333     else{
9334         switch (size) {
9335             case 1:
9336                 genlshOne (result,left,shCount);
9337                 break;
9338
9339             case 2:
9340             case 3:
9341                 genlshTwo (result,left,shCount);
9342                 break;
9343
9344             case 4:
9345                 genlshFour (result,left,shCount);
9346                 break;
9347         }
9348     }
9349     pic16_freeAsmop(left,NULL,ic,TRUE);
9350     pic16_freeAsmop(result,NULL,ic,TRUE);
9351 }
9352
9353 /*-----------------------------------------------------------------*
9354  * genMultiAsm - repeat assembly instruction for size of register.
9355  * if endian == 1, then the high byte (i.e base address + size of 
9356  * register) is used first else the low byte is used first;
9357  *-----------------------------------------------------------------*/
9358 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9359 {
9360
9361   int offset = 0;
9362
9363   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9364
9365   if(!reg)
9366     return;
9367
9368   if(!endian) {
9369     endian = 1;
9370   } else {
9371     endian = -1;
9372     offset = size-1;
9373   }
9374
9375   while(size--) {
9376     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9377     offset += endian;
9378   }
9379
9380 }
9381 /*-----------------------------------------------------------------*/
9382 /* genLeftShift - generates code for left shifting                 */
9383 /*-----------------------------------------------------------------*/
9384 static void genLeftShift (iCode *ic)
9385 {
9386   operand *left,*right, *result;
9387   int size, offset;
9388 //  char *l;
9389   symbol *tlbl , *tlbl1;
9390   pCodeOp *pctemp;
9391
9392   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9393
9394   right = IC_RIGHT(ic);
9395   left  = IC_LEFT(ic);
9396   result = IC_RESULT(ic);
9397
9398   pic16_aopOp(right,ic,FALSE);
9399
9400   /* if the shift count is known then do it 
9401      as efficiently as possible */
9402   if (AOP_TYPE(right) == AOP_LIT) {
9403     genLeftShiftLiteral (left,right,result,ic);
9404     return ;
9405   }
9406
9407   /* shift count is unknown then we have to form
9408    * a loop. Get the loop count in WREG : Note: we take
9409    * only the lower order byte since shifting
9410    * more than 32 bits make no sense anyway, ( the
9411    * largest size of an object can be only 32 bits ) */
9412   
9413   pic16_aopOp(left,ic,FALSE);
9414   pic16_aopOp(result,ic,FALSE);
9415
9416   /* now move the left to the result if they are not the
9417    * same, and if size > 1,
9418    * and if right is not same to result (!!!) -- VR */
9419   if (!pic16_sameRegs(AOP(left),AOP(result))
9420       && (AOP_SIZE(result) > 1)) {
9421
9422     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9423
9424     size = AOP_SIZE(result);
9425     offset=0;
9426     while (size--) {
9427
9428 #if 0
9429       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9430       if (*l == '@' && (IS_AOP_PREG(result))) {
9431
9432           pic16_emitcode("mov","a,%s",l);
9433           pic16_aopPut(AOP(result),"a",offset);
9434       } else
9435 #endif
9436       {
9437         /* we don't know if left is a literal or a register, take care -- VR */
9438         mov2f(AOP(result), AOP(left), offset);
9439       }
9440       offset++;
9441     }
9442   }
9443
9444   size = AOP_SIZE(result);
9445
9446   /* if it is only one byte then */
9447   if (size == 1) {
9448     if(optimized_for_speed) {
9449       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9450       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9451       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9452       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9453       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9454       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9455       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9456       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9457       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9458       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9459       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9460       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9461     } else {
9462
9463       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9464
9465       tlbl = newiTempLabel(NULL);
9466
9467 #if 1
9468       /* this is already done, why change it? */
9469       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9470                 mov2f(AOP(result), AOP(left), 0);
9471       }
9472 #endif
9473
9474       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9475       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9476       pic16_emitpLabel(tlbl->key);
9477       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9478       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9479       emitSKPC;
9480       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9481     }
9482     goto release ;
9483   }
9484     
9485   if (pic16_sameRegs(AOP(left),AOP(result))) {
9486
9487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9488     
9489     tlbl = newiTempLabel(NULL);
9490     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9491     genMultiAsm(POC_RRCF, result, size,1);
9492     pic16_emitpLabel(tlbl->key);
9493     genMultiAsm(POC_RLCF, result, size,0);
9494     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9495     emitSKPC;
9496     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9497     goto release;
9498   }
9499
9500   //tlbl = newiTempLabel(NULL);
9501   //offset = 0 ;   
9502   //tlbl1 = newiTempLabel(NULL);
9503
9504   //reAdjustPreg(AOP(result));    
9505     
9506   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9507   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9508   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9509   //MOVA(l);
9510   //pic16_emitcode("add","a,acc");         
9511   //pic16_aopPut(AOP(result),"a",offset++);
9512   //while (--size) {
9513   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9514   //  MOVA(l);
9515   //  pic16_emitcode("rlc","a");         
9516   //  pic16_aopPut(AOP(result),"a",offset++);
9517   //}
9518   //reAdjustPreg(AOP(result));
9519
9520   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9521   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9522
9523
9524   tlbl = newiTempLabel(NULL);
9525   tlbl1= newiTempLabel(NULL);
9526
9527   size = AOP_SIZE(result);
9528   offset = 1;
9529
9530   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9531
9532   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9533
9534   /* offset should be 0, 1 or 3 */
9535   
9536   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9537   emitSKPNZ;
9538   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9539
9540   pic16_emitpcode(POC_MOVWF, pctemp);
9541
9542
9543   pic16_emitpLabel(tlbl->key);
9544
9545   emitCLRC;
9546   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9547   while(--size)
9548     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9549
9550   pic16_emitpcode(POC_DECFSZ,  pctemp);
9551   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9552   pic16_emitpLabel(tlbl1->key);
9553
9554   pic16_popReleaseTempReg(pctemp,1);
9555
9556
9557  release:
9558   pic16_freeAsmop (right,NULL,ic,TRUE);
9559   pic16_freeAsmop(left,NULL,ic,TRUE);
9560   pic16_freeAsmop(result,NULL,ic,TRUE);
9561 }
9562
9563
9564
9565 #if 0
9566 #error old code (left here for reference)
9567 /*-----------------------------------------------------------------*/
9568 /* genLeftShift - generates code for left shifting                 */
9569 /*-----------------------------------------------------------------*/
9570 static void genLeftShift (iCode *ic)
9571 {
9572   operand *left,*right, *result;
9573   int size, offset;
9574   char *l;
9575   symbol *tlbl , *tlbl1;
9576   pCodeOp *pctemp;
9577
9578   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9579
9580   right = IC_RIGHT(ic);
9581   left  = IC_LEFT(ic);
9582   result = IC_RESULT(ic);
9583
9584   pic16_aopOp(right,ic,FALSE);
9585
9586   /* if the shift count is known then do it 
9587      as efficiently as possible */
9588   if (AOP_TYPE(right) == AOP_LIT) {
9589     genLeftShiftLiteral (left,right,result,ic);
9590     return ;
9591   }
9592
9593   /* shift count is unknown then we have to form 
9594      a loop get the loop count in B : Note: we take
9595      only the lower order byte since shifting
9596      more that 32 bits make no sense anyway, ( the
9597      largest size of an object can be only 32 bits ) */  
9598
9599     
9600   pic16_aopOp(left,ic,FALSE);
9601   pic16_aopOp(result,ic,FALSE);
9602
9603   /* now move the left to the result if they are not the
9604      same */
9605   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9606       AOP_SIZE(result) > 1) {
9607
9608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9609
9610     size = AOP_SIZE(result);
9611     offset=0;
9612     while (size--) {
9613       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9614       if (*l == '@' && (IS_AOP_PREG(result))) {
9615
9616         pic16_emitcode("mov","a,%s",l);
9617         pic16_aopPut(AOP(result),"a",offset);
9618       } else {
9619
9620         /* we don't know if left is a literal or a register, take care -- VR */
9621         mov2f(AOP(result), AOP(left), offset);
9622       }
9623       offset++;
9624     }
9625   }
9626
9627   size = AOP_SIZE(result);
9628
9629   /* if it is only one byte then */
9630   if (size == 1) {
9631     if(optimized_for_speed) {
9632       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9633       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9634       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9635       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9636       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9637       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9638       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9639       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9640       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9641       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9642       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9643       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9644     } else {
9645
9646       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9647
9648       tlbl = newiTempLabel(NULL);
9649       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9650                 mov2f(AOP(result), AOP(left), 0);
9651                 
9652 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9653 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9654       }
9655
9656       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9657       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9658       pic16_emitpLabel(tlbl->key);
9659       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9660       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9661       emitSKPC;
9662       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9663     }
9664     goto release ;
9665   }
9666     
9667   if (pic16_sameRegs(AOP(left),AOP(result))) {
9668
9669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9670     
9671     tlbl = newiTempLabel(NULL);
9672     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9673     genMultiAsm(POC_RRCF, result, size,1);
9674     pic16_emitpLabel(tlbl->key);
9675     genMultiAsm(POC_RLCF, result, size,0);
9676     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9677     emitSKPC;
9678     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9679     goto release;
9680   }
9681
9682   //tlbl = newiTempLabel(NULL);
9683   //offset = 0 ;   
9684   //tlbl1 = newiTempLabel(NULL);
9685
9686   //reAdjustPreg(AOP(result));    
9687     
9688   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9689   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9690   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9691   //MOVA(l);
9692   //pic16_emitcode("add","a,acc");         
9693   //pic16_aopPut(AOP(result),"a",offset++);
9694   //while (--size) {
9695   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9696   //  MOVA(l);
9697   //  pic16_emitcode("rlc","a");         
9698   //  pic16_aopPut(AOP(result),"a",offset++);
9699   //}
9700   //reAdjustPreg(AOP(result));
9701
9702   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9703   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9704
9705
9706   tlbl = newiTempLabel(NULL);
9707   tlbl1= newiTempLabel(NULL);
9708
9709   size = AOP_SIZE(result);
9710   offset = 1;
9711
9712   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9713
9714   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9715
9716   /* offset should be 0, 1 or 3 */
9717   
9718   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9719   emitSKPNZ;
9720   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9721
9722   pic16_emitpcode(POC_MOVWF, pctemp);
9723
9724
9725   pic16_emitpLabel(tlbl->key);
9726
9727   emitCLRC;
9728   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9729   while(--size)
9730     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9731
9732   pic16_emitpcode(POC_DECFSZ,  pctemp);
9733   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9734   pic16_emitpLabel(tlbl1->key);
9735
9736   pic16_popReleaseTempReg(pctemp,1);
9737
9738
9739  release:
9740   pic16_freeAsmop (right,NULL,ic,TRUE);
9741   pic16_freeAsmop(left,NULL,ic,TRUE);
9742   pic16_freeAsmop(result,NULL,ic,TRUE);
9743 }
9744 #endif
9745
9746 /*-----------------------------------------------------------------*/
9747 /* genrshOne - right shift a one byte quantity by known count      */
9748 /*-----------------------------------------------------------------*/
9749 static void genrshOne (operand *result, operand *left,
9750                        int shCount, int sign)
9751 {
9752     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9753     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9754 }
9755
9756 /*-----------------------------------------------------------------*/
9757 /* genrshTwo - right shift two bytes by known amount != 0          */
9758 /*-----------------------------------------------------------------*/
9759 static void genrshTwo (operand *result,operand *left,
9760                        int shCount, int sign)
9761 {
9762   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9763   /* if shCount >= 8 */
9764   if (shCount >= 8) {
9765     shCount -= 8 ;
9766     if (shCount)
9767       shiftR1Left2Result(left, MSB16, result, LSB,
9768                          shCount, sign);
9769     else
9770       movLeft2Result(left, MSB16, result, LSB);
9771
9772     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9773
9774     if(sign) {
9775       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9776       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9777     }
9778   }
9779
9780   /*  1 <= shCount <= 7 */
9781   else
9782     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9783 }
9784
9785 /*-----------------------------------------------------------------*/
9786 /* shiftRLong - shift right one long from left to result           */
9787 /* offl = LSB or MSB16                                             */
9788 /*-----------------------------------------------------------------*/
9789 static void shiftRLong (operand *left, int offl,
9790                         operand *result, int sign)
9791 {
9792     int size = AOP_SIZE(result);
9793     int same = pic16_sameRegs(AOP(left),AOP(result));
9794     int i;
9795     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9796
9797         if (same && (offl == MSB16)) { //shift one byte right
9798                 for(i=MSB16;i<size;i++) {
9799                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9800                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9801                 }
9802         }
9803
9804     if(sign)
9805                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9806         else
9807                 emitCLRC;
9808
9809         if (same) {
9810                 if (offl == LSB)
9811                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9812         } else {
9813         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9814         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9815         }
9816
9817     if(offl == MSB16) {
9818         /* add sign of "a" */
9819         pic16_addSign(result, MSB32, sign);
9820         }
9821
9822         if (same) {
9823         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9824         } else {
9825         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9826         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9827         }
9828         
9829         if (same) {
9830         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9831         } else {
9832         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9833         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9834         }
9835
9836         if (same) {
9837         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9838         } else {
9839         if(offl == LSB){
9840                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9841                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9842         }
9843         }
9844 }
9845
9846 /*-----------------------------------------------------------------*/
9847 /* genrshFour - shift four byte by a known amount != 0             */
9848 /*-----------------------------------------------------------------*/
9849 static void genrshFour (operand *result, operand *left,
9850                         int shCount, int sign)
9851 {
9852   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9853   /* if shifting more that 3 bytes */
9854   if(shCount >= 24 ) {
9855     shCount -= 24;
9856     if(shCount)
9857       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9858     else
9859       movLeft2Result(left, MSB32, result, LSB);
9860
9861     pic16_addSign(result, MSB16, sign);
9862   }
9863   else if(shCount >= 16){
9864     shCount -= 16;
9865     if(shCount)
9866       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9867     else{
9868       movLeft2Result(left, MSB24, result, LSB);
9869       movLeft2Result(left, MSB32, result, MSB16);
9870     }
9871     pic16_addSign(result, MSB24, sign);
9872   }
9873   else if(shCount >= 8){
9874     shCount -= 8;
9875     if(shCount == 1)
9876       shiftRLong(left, MSB16, result, sign);
9877     else if(shCount == 0){
9878       movLeft2Result(left, MSB16, result, LSB);
9879       movLeft2Result(left, MSB24, result, MSB16);
9880       movLeft2Result(left, MSB32, result, MSB24);
9881       pic16_addSign(result, MSB32, sign);
9882     }
9883     else{ //shcount >= 2
9884       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9885       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9886       /* the last shift is signed */
9887       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9888       pic16_addSign(result, MSB32, sign);
9889     }
9890   }
9891   else{   /* 1 <= shCount <= 7 */
9892     if(shCount <= 2){
9893       shiftRLong(left, LSB, result, sign);
9894       if(shCount == 2)
9895         shiftRLong(result, LSB, result, sign);
9896     }
9897     else{
9898       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9899       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9900       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9901     }
9902   }
9903 }
9904
9905 /*-----------------------------------------------------------------*/
9906 /* genRightShiftLiteral - right shifting by known count            */
9907 /*-----------------------------------------------------------------*/
9908 static void genRightShiftLiteral (operand *left,
9909                                   operand *right,
9910                                   operand *result,
9911                                   iCode *ic,
9912                                   int sign)
9913 {    
9914   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9915   int lsize,res_size;
9916
9917   pic16_freeAsmop(right,NULL,ic,TRUE);
9918
9919   pic16_aopOp(left,ic,FALSE);
9920   pic16_aopOp(result,ic,FALSE);
9921
9922   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9923
9924 #if VIEW_SIZE
9925   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9926                  AOP_SIZE(left));
9927 #endif
9928
9929   lsize = pic16_getDataSize(left);
9930   res_size = pic16_getDataSize(result);
9931   /* test the LEFT size !!! */
9932
9933   /* I suppose that the left size >= result size */
9934   if(shCount == 0){
9935     while(res_size--)
9936       movLeft2Result(left, lsize, result, res_size);
9937   }
9938
9939   else if(shCount >= (lsize * 8)){
9940
9941     if(res_size == 1) {
9942       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9943       if(sign) {
9944         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9945         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9946       }
9947     } else {
9948
9949       if(sign) {
9950         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9951         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9952         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9953         while(res_size--)
9954           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9955
9956       } else {
9957
9958         while(res_size--)
9959           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9960       }
9961     }
9962   } else {
9963
9964     switch (res_size) {
9965     case 1:
9966       genrshOne (result,left,shCount,sign);
9967       break;
9968
9969     case 2:
9970       genrshTwo (result,left,shCount,sign);
9971       break;
9972
9973     case 4:
9974       genrshFour (result,left,shCount,sign);
9975       break;
9976     default :
9977       break;
9978     }
9979
9980   }
9981
9982   pic16_freeAsmop(left,NULL,ic,TRUE);
9983   pic16_freeAsmop(result,NULL,ic,TRUE);
9984 }
9985
9986 /*-----------------------------------------------------------------*/
9987 /* genSignedRightShift - right shift of signed number              */
9988 /*-----------------------------------------------------------------*/
9989 static void genSignedRightShift (iCode *ic)
9990 {
9991   operand *right, *left, *result;
9992   int size, offset;
9993   //  char *l;
9994   symbol *tlbl, *tlbl1 ;
9995   pCodeOp *pctemp;
9996
9997   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9998
9999   /* we do it the hard way put the shift count in b
10000      and loop thru preserving the sign */
10001   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10002
10003   right = IC_RIGHT(ic);
10004   left  = IC_LEFT(ic);
10005   result = IC_RESULT(ic);
10006
10007   pic16_aopOp(right,ic,FALSE);  
10008   pic16_aopOp(left,ic,FALSE);
10009   pic16_aopOp(result,ic,FALSE);
10010
10011
10012   if ( AOP_TYPE(right) == AOP_LIT) {
10013     genRightShiftLiteral (left,right,result,ic,1);
10014     return ;
10015   }
10016   /* shift count is unknown then we have to form 
10017      a loop get the loop count in B : Note: we take
10018      only the lower order byte since shifting
10019      more that 32 bits make no sense anyway, ( the
10020      largest size of an object can be only 32 bits ) */  
10021
10022   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10023   //pic16_emitcode("inc","b");
10024   //pic16_freeAsmop (right,NULL,ic,TRUE);
10025   //pic16_aopOp(left,ic,FALSE);
10026   //pic16_aopOp(result,ic,FALSE);
10027
10028   /* now move the left to the result if they are not the
10029      same */
10030   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10031       AOP_SIZE(result) > 1) {
10032
10033     size = AOP_SIZE(result);
10034     offset=0;
10035     while (size--) { 
10036       /*
10037         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10038         if (*l == '@' && IS_AOP_PREG(result)) {
10039
10040         pic16_emitcode("mov","a,%s",l);
10041         pic16_aopPut(AOP(result),"a",offset);
10042         } else
10043         pic16_aopPut(AOP(result),l,offset);
10044       */
10045       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10046       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10047
10048       offset++;
10049     }
10050   }
10051
10052   /* mov the highest order bit to OVR */    
10053   tlbl = newiTempLabel(NULL);
10054   tlbl1= newiTempLabel(NULL);
10055
10056   size = AOP_SIZE(result);
10057   offset = size - 1;
10058
10059   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10060
10061   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10062
10063   /* offset should be 0, 1 or 3 */
10064   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10065   emitSKPNZ;
10066   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10067
10068   pic16_emitpcode(POC_MOVWF, pctemp);
10069
10070
10071   pic16_emitpLabel(tlbl->key);
10072
10073   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10074   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10075
10076   while(--size) {
10077     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10078   }
10079
10080   pic16_emitpcode(POC_DECFSZ,  pctemp);
10081   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10082   pic16_emitpLabel(tlbl1->key);
10083
10084   pic16_popReleaseTempReg(pctemp,1);
10085 #if 0
10086   size = AOP_SIZE(result);
10087   offset = size - 1;
10088   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10089   pic16_emitcode("rlc","a");
10090   pic16_emitcode("mov","ov,c");
10091   /* if it is only one byte then */
10092   if (size == 1) {
10093     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10094     MOVA(l);
10095     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10096     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10097     pic16_emitcode("mov","c,ov");
10098     pic16_emitcode("rrc","a");
10099     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10100     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10101     pic16_aopPut(AOP(result),"a",0);
10102     goto release ;
10103   }
10104
10105   reAdjustPreg(AOP(result));
10106   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10107   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10108   pic16_emitcode("mov","c,ov");
10109   while (size--) {
10110     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10111     MOVA(l);
10112     pic16_emitcode("rrc","a");         
10113     pic16_aopPut(AOP(result),"a",offset--);
10114   }
10115   reAdjustPreg(AOP(result));
10116   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10117   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10118
10119  release:
10120 #endif
10121
10122   pic16_freeAsmop(left,NULL,ic,TRUE);
10123   pic16_freeAsmop(result,NULL,ic,TRUE);
10124   pic16_freeAsmop(right,NULL,ic,TRUE);
10125 }
10126
10127 /*-----------------------------------------------------------------*/
10128 /* genRightShift - generate code for right shifting                */
10129 /*-----------------------------------------------------------------*/
10130 static void genRightShift (iCode *ic)
10131 {
10132     operand *right, *left, *result;
10133     sym_link *letype ;
10134     int size, offset;
10135     char *l;
10136     symbol *tlbl, *tlbl1 ;
10137
10138     /* if signed then we do it the hard way preserve the
10139     sign bit moving it inwards */
10140     letype = getSpec(operandType(IC_LEFT(ic)));
10141     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10142
10143     if (!SPEC_USIGN(letype)) {
10144         genSignedRightShift (ic);
10145         return ;
10146     }
10147
10148     /* signed & unsigned types are treated the same : i.e. the
10149     signed is NOT propagated inwards : quoting from the
10150     ANSI - standard : "for E1 >> E2, is equivalent to division
10151     by 2**E2 if unsigned or if it has a non-negative value,
10152     otherwise the result is implementation defined ", MY definition
10153     is that the sign does not get propagated */
10154
10155     right = IC_RIGHT(ic);
10156     left  = IC_LEFT(ic);
10157     result = IC_RESULT(ic);
10158
10159     pic16_aopOp(right,ic,FALSE);
10160
10161     /* if the shift count is known then do it 
10162     as efficiently as possible */
10163     if (AOP_TYPE(right) == AOP_LIT) {
10164         genRightShiftLiteral (left,right,result,ic, 0);
10165         return ;
10166     }
10167
10168     /* shift count is unknown then we have to form 
10169     a loop get the loop count in B : Note: we take
10170     only the lower order byte since shifting
10171     more that 32 bits make no sense anyway, ( the
10172     largest size of an object can be only 32 bits ) */  
10173
10174     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10175     pic16_emitcode("inc","b");
10176     pic16_aopOp(left,ic,FALSE);
10177     pic16_aopOp(result,ic,FALSE);
10178
10179     /* now move the left to the result if they are not the
10180     same */
10181     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10182         AOP_SIZE(result) > 1) {
10183
10184         size = AOP_SIZE(result);
10185         offset=0;
10186         while (size--) {
10187             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10188             if (*l == '@' && IS_AOP_PREG(result)) {
10189
10190                 pic16_emitcode("mov","a,%s",l);
10191                 pic16_aopPut(AOP(result),"a",offset);
10192             } else
10193                 pic16_aopPut(AOP(result),l,offset);
10194             offset++;
10195         }
10196     }
10197
10198     tlbl = newiTempLabel(NULL);
10199     tlbl1= newiTempLabel(NULL);
10200     size = AOP_SIZE(result);
10201     offset = size - 1;
10202
10203     /* if it is only one byte then */
10204     if (size == 1) {
10205
10206       tlbl = newiTempLabel(NULL);
10207       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10208         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10209         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10210       }
10211
10212       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10213       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10214       pic16_emitpLabel(tlbl->key);
10215       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10216       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10217       emitSKPC;
10218       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10219
10220       goto release ;
10221     }
10222
10223     reAdjustPreg(AOP(result));
10224     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10225     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10226     CLRC;
10227     while (size--) {
10228         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10229         MOVA(l);
10230         pic16_emitcode("rrc","a");         
10231         pic16_aopPut(AOP(result),"a",offset--);
10232     }
10233     reAdjustPreg(AOP(result));
10234
10235     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10237
10238 release:
10239     pic16_freeAsmop(left,NULL,ic,TRUE);
10240     pic16_freeAsmop (right,NULL,ic,TRUE);
10241     pic16_freeAsmop(result,NULL,ic,TRUE);
10242 }
10243
10244
10245 void pic16_loadFSR0(operand *op)
10246 {
10247         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10248 }
10249
10250 /*-----------------------------------------------------------------*/
10251 /* genUnpackBits - generates code for unpacking bits               */
10252 /*-----------------------------------------------------------------*/
10253 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10254 {    
10255   int shCnt ;
10256   int rlen = 0 ;
10257   sym_link *etype, *letype;
10258   int blen=0, bstr=0;
10259   int lbstr;
10260   int offset = 0 ;
10261
10262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10263     etype = getSpec(operandType(result));
10264     letype = getSpec(operandType(left));
10265     
10266 //    if(IS_BITFIELD(etype)) {
10267       blen = SPEC_BLEN(etype);
10268       bstr = SPEC_BSTR(etype);
10269 //    }
10270
10271     lbstr = SPEC_BSTR( letype );
10272
10273 #if 1
10274     if((blen == 1) && (bstr < 8)) {
10275       /* it is a single bit, so use the appropriate bit instructions */
10276       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10277
10278       if(IS_BITFIELD(etype)/* && !IS_ITEMP(left)*/) {
10279         pic16_emitpcode(POC_MOVFW, pic16_popGet( AOP(result), 0 ));
10280         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10281       } else {
10282         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10283       }
10284       
10285       if((ptype == POINTER) && (result)) {
10286         /* workaround to reduce the extra lfsr instruction */
10287         pic16_emitpcode(POC_BTFSC,
10288               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10289       } else {
10290         pic16_emitpcode(POC_BTFSC,
10291               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10292       }
10293         
10294
10295       if(IS_BITFIELD(etype)) {
10296         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10297       } else {
10298         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10299       }      
10300
10301       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10302       return;
10303     }
10304
10305 #endif
10306
10307         /* the following call to pic16_loadFSR0 is temporary until
10308          * optimization to handle single bit assignments is added
10309          * to the function. Until then use the old safe way! -- VR */
10310         pic16_loadFSR0( left );
10311  
10312         /* read the first byte  */
10313         switch (ptype) {
10314                 case POINTER:
10315                 case IPOINTER:
10316                 case PPOINTER:
10317                 case FPOINTER:
10318                 case GPOINTER:
10319                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10320                         break;
10321                 case CPOINTER:
10322                         pic16_emitcode("clr","a");
10323                         pic16_emitcode("movc","a","@a+dptr");
10324                         break;
10325         }
10326         
10327
10328         /* if we have bitdisplacement then it fits   */
10329         /* into this byte completely or if length is */
10330         /* less than a byte                          */
10331         if ((shCnt = SPEC_BSTR(etype)) || 
10332                 (SPEC_BLEN(etype) <= 8))  {
10333
10334                 /* shift right acc */
10335                 AccRsh(shCnt, 0);
10336
10337                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10338                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10339
10340 /* VR -- normally I would use the following, but since we use the hack,
10341  * to avoid the masking from AccRsh, why not mask it right now? */
10342
10343 /*
10344                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10345 */
10346
10347                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10348           return ;
10349         }
10350
10351
10352
10353         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10354         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10355         exit(-1);
10356
10357     /* bit field did not fit in a byte  */
10358     rlen = SPEC_BLEN(etype) - 8;
10359     pic16_aopPut(AOP(result),"a",offset++);
10360
10361     while (1)  {
10362
10363         switch (ptype) {
10364         case POINTER:
10365         case IPOINTER:
10366             pic16_emitcode("inc","%s",rname);
10367             pic16_emitcode("mov","a,@%s",rname);
10368             break;
10369             
10370         case PPOINTER:
10371             pic16_emitcode("inc","%s",rname);
10372             pic16_emitcode("movx","a,@%s",rname);
10373             break;
10374
10375         case FPOINTER:
10376             pic16_emitcode("inc","dptr");
10377             pic16_emitcode("movx","a,@dptr");
10378             break;
10379             
10380         case CPOINTER:
10381             pic16_emitcode("clr","a");
10382             pic16_emitcode("inc","dptr");
10383             pic16_emitcode("movc","a","@a+dptr");
10384             break;
10385             
10386         case GPOINTER:
10387             pic16_emitcode("inc","dptr");
10388             pic16_emitcode("lcall","__gptrget");
10389             break;
10390         }
10391
10392         rlen -= 8;            
10393         /* if we are done */
10394         if ( rlen <= 0 )
10395             break ;
10396         
10397         pic16_aopPut(AOP(result),"a",offset++);
10398                               
10399     }
10400     
10401     if (rlen) {
10402         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10403         pic16_aopPut(AOP(result),"a",offset);          
10404     }
10405     
10406     return ;
10407 }
10408
10409
10410 static void genDataPointerGet(operand *left,
10411                               operand *result,
10412                               iCode *ic)
10413 {
10414   int size, offset = 0, leoffset=0 ;
10415
10416         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10417         pic16_aopOp(result, ic, FALSE);
10418
10419         size = AOP_SIZE(result);
10420 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10421
10422
10423 #if 0
10424         /* The following tests may save a redudant movff instruction when
10425          * accessing unions */
10426          
10427         /* if they are the same */
10428         if (operandsEqu (left, result)) {
10429                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10430                 goto release;
10431         }
10432 #endif
10433
10434 #if 0
10435         /* if they are the same registers */
10436         if (pic16_sameRegs(AOP(left),AOP(result))) {
10437                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10438                 goto release;
10439         }
10440 #endif
10441
10442 #if 1
10443         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10444                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10445                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10446                 goto release;
10447         }
10448 #endif
10449
10450
10451 #if 0
10452         if ( AOP_TYPE(left) == AOP_PCODE) {
10453                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10454                                 AOP(left)->aopu.pcop->name,
10455                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10456                                 PCOR(AOP(left)->aopu.pcop)->instance:
10457                                 PCOI(AOP(left)->aopu.pcop)->offset);
10458         }
10459 #endif
10460
10461         if(AOP(left)->aopu.pcop->type == PO_DIR)
10462                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10463
10464         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10465
10466         while (size--) {
10467                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10468                 
10469                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10470                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10471                         mov2w(AOP(left), offset); // patch 8
10472                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10473                 } else {
10474                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10475                                 pic16_popGet(AOP(left), offset), //patch 8
10476                                 pic16_popGet(AOP(result), offset)));
10477                 }
10478
10479                 offset++;
10480                 leoffset++;
10481         }
10482
10483 release:
10484     pic16_freeAsmop(result,NULL,ic,TRUE);
10485 }
10486
10487
10488
10489 /*-----------------------------------------------------------------*/
10490 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10491 /*-----------------------------------------------------------------*/
10492 static void genNearPointerGet (operand *left, 
10493                                operand *result, 
10494                                iCode *ic)
10495 {
10496     asmop *aop = NULL;
10497     //regs *preg = NULL ;
10498     sym_link *rtype, *retype;
10499     sym_link *ltype = operandType(left);    
10500
10501         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10502         rtype = operandType(result);
10503         retype= getSpec(rtype);
10504     
10505         pic16_aopOp(left,ic,FALSE);
10506
10507 //      pic16_DumpOp("(left)",left);
10508 //      pic16_DumpOp("(result)",result);
10509
10510         /* if left is rematerialisable and
10511          * result is not bit variable type and
10512          * the left is pointer to data space i.e
10513          * lower 128 bytes of space */
10514         if (AOP_TYPE(left) == AOP_PCODE
10515                 && !IS_BITFIELD(retype)
10516                 && DCL_TYPE(ltype) == POINTER) {
10517
10518                 genDataPointerGet (left,result,ic);
10519                 pic16_freeAsmop(left, NULL, ic, TRUE);
10520           return ;
10521         }
10522     
10523         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10524
10525         /* if the value is already in a pointer register
10526          * then don't need anything more */
10527         if (!AOP_INPREG(AOP(left))) {
10528                 /* otherwise get a free pointer register */
10529                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10530                 
10531                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10532                 if( (AOP_TYPE(left) == AOP_PCODE) 
10533                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10534                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
10535                 {
10536                         if(!IS_BITFIELD(retype))
10537                                 pic16_loadFSR0( left );  // patch 10
10538                 } else {
10539                   if(!IS_BITFIELD(retype)) {
10540                     // set up FSR0 with address from left
10541                     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10542                     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10543                   }
10544                 }
10545         }
10546 //       else
10547 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10548     
10549     pic16_aopOp (result,ic,FALSE);
10550     
10551     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10552
10553       /* if bitfield then unpack the bits */
10554     if (IS_BITFIELD(retype)) 
10555         genUnpackBits (result, left, NULL, POINTER);
10556     else {
10557         /* we have can just get the values */
10558       int size = AOP_SIZE(result);
10559       int offset = 0;   
10560         
10561       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10562
10563
10564         /* fsr0 is loaded already -- VR */
10565 //      pic16_loadFSR0( left );
10566
10567 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10568 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10569       while(size--) {
10570
10571         if(size) {
10572                 pic16_emitpcode(POC_MOVFF,
10573                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10574                                 pic16_popGet(AOP(result), offset++)));
10575         } else {
10576                 pic16_emitpcode(POC_MOVFF,
10577                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10578                                 pic16_popGet(AOP(result), offset++)));
10579         }
10580       }
10581 #if 0
10582 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10583 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10584         if(size)
10585           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10586 #endif
10587 /*
10588         while (size--) {
10589             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10590
10591                 pic16_emitcode("mov","a,@%s",rname);
10592                 pic16_aopPut(AOP(result),"a",offset);
10593             } else {
10594                 sprintf(buffer,"@%s",rname);
10595                 pic16_aopPut(AOP(result),buffer,offset);
10596             }
10597             offset++ ;
10598             if (size)
10599                 pic16_emitcode("inc","%s",rname);
10600         }
10601 */
10602     }
10603
10604     /* now some housekeeping stuff */
10605     if (aop) {
10606         /* we had to allocate for this iCode */
10607     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10608         pic16_freeAsmop(NULL,aop,ic,TRUE);
10609     } else { 
10610         /* we did not allocate which means left
10611            already in a pointer register, then
10612            if size > 0 && this could be used again
10613            we have to point it back to where it 
10614            belongs */
10615     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10616         if (AOP_SIZE(result) > 1 &&
10617             !OP_SYMBOL(left)->remat &&
10618             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10619               ic->depth )) {
10620 //          int size = AOP_SIZE(result) - 1;
10621 //          while (size--)
10622 //              pic16_emitcode("dec","%s",rname);
10623         }
10624     }
10625
10626     /* done */
10627     pic16_freeAsmop(left,NULL,ic,TRUE);
10628     pic16_freeAsmop(result,NULL,ic,TRUE);
10629      
10630 }
10631
10632 /*-----------------------------------------------------------------*/
10633 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10634 /*-----------------------------------------------------------------*/
10635 static void genPagedPointerGet (operand *left, 
10636                                operand *result, 
10637                                iCode *ic)
10638 {
10639     asmop *aop = NULL;
10640     regs *preg = NULL ;
10641     char *rname ;
10642     sym_link *rtype, *retype;    
10643
10644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10645
10646     rtype = operandType(result);
10647     retype= getSpec(rtype);
10648     
10649     pic16_aopOp(left,ic,FALSE);
10650
10651   /* if the value is already in a pointer register
10652        then don't need anything more */
10653     if (!AOP_INPREG(AOP(left))) {
10654         /* otherwise get a free pointer register */
10655         aop = newAsmop(0);
10656         preg = getFreePtr(ic,&aop,FALSE);
10657         pic16_emitcode("mov","%s,%s",
10658                 preg->name,
10659                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10660         rname = preg->name ;
10661     } else
10662         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10663     
10664     pic16_freeAsmop(left,NULL,ic,TRUE);
10665     pic16_aopOp (result,ic,FALSE);
10666
10667     /* if bitfield then unpack the bits */
10668     if (IS_BITFIELD(retype)) 
10669         genUnpackBits (result,left,rname,PPOINTER);
10670     else {
10671         /* we have can just get the values */
10672         int size = AOP_SIZE(result);
10673         int offset = 0 ;        
10674         
10675         while (size--) {
10676             
10677             pic16_emitcode("movx","a,@%s",rname);
10678             pic16_aopPut(AOP(result),"a",offset);
10679             
10680             offset++ ;
10681             
10682             if (size)
10683                 pic16_emitcode("inc","%s",rname);
10684         }
10685     }
10686
10687     /* now some housekeeping stuff */
10688     if (aop) {
10689         /* we had to allocate for this iCode */
10690         pic16_freeAsmop(NULL,aop,ic,TRUE);
10691     } else { 
10692         /* we did not allocate which means left
10693            already in a pointer register, then
10694            if size > 0 && this could be used again
10695            we have to point it back to where it 
10696            belongs */
10697         if (AOP_SIZE(result) > 1 &&
10698             !OP_SYMBOL(left)->remat &&
10699             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10700               ic->depth )) {
10701             int size = AOP_SIZE(result) - 1;
10702             while (size--)
10703                 pic16_emitcode("dec","%s",rname);
10704         }
10705     }
10706
10707     /* done */
10708     pic16_freeAsmop(result,NULL,ic,TRUE);
10709     
10710         
10711 }
10712
10713 /*-----------------------------------------------------------------*/
10714 /* genFarPointerGet - gget value from far space                    */
10715 /*-----------------------------------------------------------------*/
10716 static void genFarPointerGet (operand *left,
10717                               operand *result, iCode *ic)
10718 {
10719     int size, offset ;
10720     sym_link *retype = getSpec(operandType(result));
10721
10722     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10723
10724     pic16_aopOp(left,ic,FALSE);
10725
10726     /* if the operand is already in dptr 
10727     then we do nothing else we move the value to dptr */
10728     if (AOP_TYPE(left) != AOP_STR) {
10729         /* if this is remateriazable */
10730         if (AOP_TYPE(left) == AOP_IMMD)
10731             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10732         else { /* we need to get it byte by byte */
10733             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10734             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10735             if (options.model == MODEL_FLAT24)
10736             {
10737                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10738             }
10739         }
10740     }
10741     /* so dptr know contains the address */
10742     pic16_freeAsmop(left,NULL,ic,TRUE);
10743     pic16_aopOp(result,ic,FALSE);
10744
10745     /* if bit then unpack */
10746     if (IS_BITFIELD(retype)) 
10747         genUnpackBits(result,left,"dptr",FPOINTER);
10748     else {
10749         size = AOP_SIZE(result);
10750         offset = 0 ;
10751
10752         while (size--) {
10753             pic16_emitcode("movx","a,@dptr");
10754             pic16_aopPut(AOP(result),"a",offset++);
10755             if (size)
10756                 pic16_emitcode("inc","dptr");
10757         }
10758     }
10759
10760     pic16_freeAsmop(result,NULL,ic,TRUE);
10761 }
10762 #if 0
10763 /*-----------------------------------------------------------------*/
10764 /* genCodePointerGet - get value from code space                  */
10765 /*-----------------------------------------------------------------*/
10766 static void genCodePointerGet (operand *left,
10767                                 operand *result, iCode *ic)
10768 {
10769     int size, offset ;
10770     sym_link *retype = getSpec(operandType(result));
10771
10772     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10773
10774     pic16_aopOp(left,ic,FALSE);
10775
10776     /* if the operand is already in dptr 
10777     then we do nothing else we move the value to dptr */
10778     if (AOP_TYPE(left) != AOP_STR) {
10779         /* if this is remateriazable */
10780         if (AOP_TYPE(left) == AOP_IMMD)
10781             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10782         else { /* we need to get it byte by byte */
10783             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10784             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10785             if (options.model == MODEL_FLAT24)
10786             {
10787                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10788             }
10789         }
10790     }
10791     /* so dptr know contains the address */
10792     pic16_freeAsmop(left,NULL,ic,TRUE);
10793     pic16_aopOp(result,ic,FALSE);
10794
10795     /* if bit then unpack */
10796     if (IS_BITFIELD(retype)) 
10797         genUnpackBits(result,left,"dptr",CPOINTER);
10798     else {
10799         size = AOP_SIZE(result);
10800         offset = 0 ;
10801
10802         while (size--) {
10803             pic16_emitcode("clr","a");
10804             pic16_emitcode("movc","a,@a+dptr");
10805             pic16_aopPut(AOP(result),"a",offset++);
10806             if (size)
10807                 pic16_emitcode("inc","dptr");
10808         }
10809     }
10810
10811     pic16_freeAsmop(result,NULL,ic,TRUE);
10812 }
10813 #endif
10814 #if 0
10815 /*-----------------------------------------------------------------*/
10816 /* genGenPointerGet - gget value from generic pointer space        */
10817 /*-----------------------------------------------------------------*/
10818 static void genGenPointerGet (operand *left,
10819                               operand *result, iCode *ic)
10820 {
10821   int size, offset, lit;
10822   sym_link *retype = getSpec(operandType(result));
10823
10824         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10825         pic16_aopOp(left,ic,FALSE);
10826         pic16_aopOp(result,ic,FALSE);
10827         size = AOP_SIZE(result);
10828
10829         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10830
10831         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10832
10833                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10834                 // load FSR0 from immediate
10835                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10836
10837 //              pic16_loadFSR0( left );
10838
10839                 offset = 0;
10840                 while(size--) {
10841                         if(size) {
10842                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10843                         } else {
10844                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10845                         }
10846                         offset++;
10847                 }
10848                 goto release;
10849
10850         }
10851         else { /* we need to get it byte by byte */
10852                 // set up FSR0 with address from left
10853                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10854                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10855
10856                 offset = 0 ;
10857
10858                 while(size--) {
10859                         if(size) {
10860                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10861                         } else {
10862                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10863                         }
10864                         offset++;
10865                 }
10866                 goto release;
10867         }
10868
10869   /* if bit then unpack */
10870         if (IS_BITFIELD(retype)) 
10871                 genUnpackBits(result,left,"BAD",GPOINTER);
10872
10873         release:
10874         pic16_freeAsmop(left,NULL,ic,TRUE);
10875         pic16_freeAsmop(result,NULL,ic,TRUE);
10876
10877 }
10878 #endif
10879
10880
10881 /*-----------------------------------------------------------------*/
10882 /* genGenPointerGet - gget value from generic pointer space        */
10883 /*-----------------------------------------------------------------*/
10884 static void genGenPointerGet (operand *left,
10885                               operand *result, iCode *ic)
10886 {
10887   int size, offset, lit;
10888   sym_link *retype = getSpec(operandType(result));
10889   char fgptrget[32];
10890
10891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10892     pic16_aopOp(left,ic,FALSE);
10893     pic16_aopOp(result,ic,FALSE);
10894     size = AOP_SIZE(result);
10895
10896     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10897
10898     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10899
10900       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10901       // load FSR0 from immediate
10902       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10903
10904       werror(W_POSSBUG2, __FILE__, __LINE__);
10905
10906       offset = 0;
10907       while(size--) {
10908         if(size) {
10909           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10910         } else {
10911           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10912         }
10913         offset++;
10914       }
10915
10916       goto release;
10917
10918     } else { /* we need to get it byte by byte */
10919
10920       /* set up WREG:PRODL:FSR0L with address from left */
10921       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10922       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10923       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10924       
10925       switch( size ) {
10926         case 1: strcpy(fgptrget, "__gptrget1"); break;
10927         case 2: strcpy(fgptrget, "__gptrget2"); break;
10928         case 3: strcpy(fgptrget, "__gptrget3"); break;
10929         case 4: strcpy(fgptrget, "__gptrget4"); break;
10930         default:
10931           werror(W_POSSBUG2, __FILE__, __LINE__);
10932           abort();
10933       }
10934       
10935       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10936       
10937       assignResultValue(result, 1);
10938       
10939       {
10940         symbol *sym;
10941
10942           sym = newSymbol( fgptrget, 0 );
10943           strcpy(sym->rname, fgptrget);
10944           checkAddSym(&externs, sym);
10945
10946 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10947       }
10948               
10949       goto release;
10950     }
10951
10952   /* if bit then unpack */
10953     if (IS_BITFIELD(retype)) 
10954       genUnpackBits(result,left,"BAD",GPOINTER);
10955
10956 release:
10957   pic16_freeAsmop(left,NULL,ic,TRUE);
10958   pic16_freeAsmop(result,NULL,ic,TRUE);
10959 }
10960
10961 /*-----------------------------------------------------------------*/
10962 /* genConstPointerGet - get value from const generic pointer space */
10963 /*-----------------------------------------------------------------*/
10964 static void genConstPointerGet (operand *left,
10965                                 operand *result, iCode *ic)
10966 {
10967   //sym_link *retype = getSpec(operandType(result));
10968   // symbol *albl = newiTempLabel(NULL);        // patch 15
10969   // symbol *blbl = newiTempLabel(NULL);        //
10970   // PIC_OPCODE poc;                            // patch 15
10971   int size;
10972   int offset = 0;
10973
10974   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10975   pic16_aopOp(left,ic,FALSE);
10976   pic16_aopOp(result,ic,TRUE);
10977   size = AOP_SIZE(result);
10978
10979   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10980
10981   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10982 #if 0                                                                   // patch 15
10983   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10984   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10985   pic16_emitpLabel(albl->key);
10986
10987   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10988   
10989   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10990   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10991   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10992   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10993   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10994
10995   pic16_emitpLabel(blbl->key);
10996
10997   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10998 #endif                                                                  // patch 15
10999
11000
11001   // set up table pointer
11002   if( (AOP_TYPE(left) == AOP_PCODE) 
11003       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11004           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11005     {
11006       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11007       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11008       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11009       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11010       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11011       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11012     }
11013   else
11014     {
11015       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11016       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11017       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11018     }
11019
11020
11021   while(size--)
11022     {
11023       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11024       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11025       offset++;
11026     }
11027     
11028   pic16_freeAsmop(left,NULL,ic,TRUE);
11029   pic16_freeAsmop(result,NULL,ic,TRUE);
11030
11031 }
11032
11033
11034 /*-----------------------------------------------------------------*/
11035 /* genPointerGet - generate code for pointer get                   */
11036 /*-----------------------------------------------------------------*/
11037 static void genPointerGet (iCode *ic)
11038 {
11039     operand *left, *result ;
11040     sym_link *type, *etype;
11041     int p_type;
11042
11043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11044
11045     left = IC_LEFT(ic);
11046     result = IC_RESULT(ic) ;
11047
11048     /* depending on the type of pointer we need to
11049     move it to the correct pointer register */
11050     type = operandType(left);
11051     etype = getSpec(type);
11052
11053 #if 0
11054     if (IS_PTR_CONST(type))
11055 #else
11056     if (IS_CODEPTR(type))
11057 #endif
11058       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11059
11060     /* if left is of type of pointer then it is simple */
11061     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11062         p_type = DCL_TYPE(type);
11063     else {
11064         /* we have to go by the storage class */
11065         p_type = PTR_TYPE(SPEC_OCLS(etype));
11066
11067         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11068
11069         if (SPEC_OCLS(etype)->codesp ) {
11070           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11071           //p_type = CPOINTER ; 
11072         }
11073         else
11074             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11075               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11076                /*p_type = FPOINTER ;*/ 
11077             else
11078                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11079                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11080 /*                  p_type = PPOINTER; */
11081                 else
11082                     if (SPEC_OCLS(etype) == idata )
11083                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11084 /*                      p_type = IPOINTER; */
11085                     else
11086                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11087 /*                      p_type = POINTER ; */
11088     }
11089
11090     /* now that we have the pointer type we assign
11091     the pointer values */
11092     switch (p_type) {
11093
11094     case POINTER:       
11095     case IPOINTER:
11096         genNearPointerGet (left,result,ic);
11097         break;
11098
11099     case PPOINTER:
11100         genPagedPointerGet(left,result,ic);
11101         break;
11102
11103     case FPOINTER:
11104         genFarPointerGet (left,result,ic);
11105         break;
11106
11107     case CPOINTER:
11108         genConstPointerGet (left,result,ic);
11109         //pic16_emitcodePointerGet (left,result,ic);
11110         break;
11111
11112     case GPOINTER:
11113 #if 0
11114       if (IS_PTR_CONST(type))
11115         genConstPointerGet (left,result,ic);
11116       else
11117 #endif
11118         genGenPointerGet (left,result,ic);
11119       break;
11120
11121     default:
11122       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11123               "genPointerGet: illegal pointer type");
11124     
11125     }
11126
11127 }
11128
11129 /*-----------------------------------------------------------------*/
11130 /* genPackBits - generates code for packed bit storage             */
11131 /*-----------------------------------------------------------------*/
11132 static void genPackBits (sym_link    *etype , operand *result,
11133                          operand *right ,
11134                          char *rname, int p_type)
11135 {
11136   int shCnt = 0 ;
11137   int offset = 0  ;
11138   int rLen = 0 ;
11139   int blen, bstr ;   
11140   sym_link *retype;
11141   char *l ;
11142
11143         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11144         blen = SPEC_BLEN(etype);
11145         bstr = SPEC_BSTR(etype);
11146
11147         retype = getSpec(operandType(right));
11148
11149         if(AOP_TYPE(right) == AOP_LIT) {
11150                 if((blen == 1) && (bstr < 8)) {
11151                   unsigned long lit;
11152                         /* it is a single bit, so use the appropriate bit instructions */
11153
11154                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11155
11156                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11157 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11158                         if((p_type == POINTER) && (result)) {
11159                                 /* workaround to reduce the extra lfsr instruction */
11160                                 if(lit) {
11161                                         pic16_emitpcode(POC_BSF,
11162                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11163                                 } else {
11164                                         pic16_emitpcode(POC_BCF,
11165                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11166                                 }
11167                         } else {
11168
11169                                 if(lit) {
11170                                         pic16_emitpcode(POC_BSF,
11171                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11172                                 } else {
11173                                         pic16_emitpcode(POC_BCF,
11174                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11175                                 }
11176                         }
11177         
11178                   return;
11179                 }
11180
11181                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11182                 offset++;
11183         } else
11184         if(IS_BITFIELD(retype) 
11185           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11186           && (blen == 1)) {
11187           int rblen, rbstr;
11188
11189             rblen = SPEC_BLEN( retype );
11190             rbstr = SPEC_BSTR( retype );
11191             
11192
11193             if(IS_BITFIELD(etype)) {
11194               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11195               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11196             } else {
11197               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11198             }
11199             
11200             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11201             
11202             if(IS_BITFIELD(etype)) {
11203               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11204             } else {
11205               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11206             }
11207
11208             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11209             
11210             return;
11211         } else
11212           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11213
11214         /* if the bit lenth is less than or    */
11215         /* it exactly fits a byte then         */
11216         if((shCnt=SPEC_BSTR(etype))
11217                 || SPEC_BLEN(etype) <= 8 )  {
11218
11219                 /* shift left acc */
11220                 AccLsh(shCnt);
11221
11222                 /* using PRODL as a temporary register here */
11223                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11224
11225                 switch (p_type) {
11226                         case FPOINTER:
11227                         case POINTER:
11228                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11229 //                              pic16_emitcode ("mov","b,a");
11230 //                              pic16_emitcode("mov","a,@%s",rname);
11231                                 break;
11232
11233                         case GPOINTER:
11234                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11235                                 break;
11236
11237                 }
11238 #if 1
11239                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11240                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11241                                         (unsigned char)(0xff >> (8-bstr))) ));
11242                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11243                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11244 #endif
11245
11246           return;
11247         }
11248
11249
11250         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11251         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11252         exit(-1);
11253
11254
11255     /* if we r done */
11256     if ( SPEC_BLEN(etype) <= 8 )
11257         return ;
11258
11259     pic16_emitcode("inc","%s",rname);
11260     rLen = SPEC_BLEN(etype) ;     
11261
11262
11263
11264     /* now generate for lengths greater than one byte */
11265     while (1) {
11266
11267         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11268
11269         rLen -= 8 ;
11270         if (rLen <= 0 )
11271             break ;
11272
11273         switch (p_type) {
11274             case POINTER:
11275                 if (*l == '@') {
11276                     MOVA(l);
11277                     pic16_emitcode("mov","@%s,a",rname);
11278                 } else
11279                     pic16_emitcode("mov","@%s,%s",rname,l);
11280                 break;
11281
11282             case FPOINTER:
11283                 MOVA(l);
11284                 pic16_emitcode("movx","@dptr,a");
11285                 break;
11286
11287             case GPOINTER:
11288                 MOVA(l);
11289                 DEBUGpic16_emitcode(";lcall","__gptrput");
11290                 break;  
11291         }   
11292         pic16_emitcode ("inc","%s",rname);
11293     }
11294
11295     MOVA(l);
11296
11297     /* last last was not complete */
11298     if (rLen)   {
11299         /* save the byte & read byte */
11300         switch (p_type) {
11301             case POINTER:
11302                 pic16_emitcode ("mov","b,a");
11303                 pic16_emitcode("mov","a,@%s",rname);
11304                 break;
11305
11306             case FPOINTER:
11307                 pic16_emitcode ("mov","b,a");
11308                 pic16_emitcode("movx","a,@dptr");
11309                 break;
11310
11311             case GPOINTER:
11312                 pic16_emitcode ("push","b");
11313                 pic16_emitcode ("push","acc");
11314                 pic16_emitcode ("lcall","__gptrget");
11315                 pic16_emitcode ("pop","b");
11316                 break;
11317         }
11318
11319         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11320         pic16_emitcode ("orl","a,b");
11321     }
11322
11323     if (p_type == GPOINTER)
11324         pic16_emitcode("pop","b");
11325
11326     switch (p_type) {
11327
11328     case POINTER:
11329         pic16_emitcode("mov","@%s,a",rname);
11330         break;
11331         
11332     case FPOINTER:
11333         pic16_emitcode("movx","@dptr,a");
11334         break;
11335         
11336     case GPOINTER:
11337         DEBUGpic16_emitcode(";lcall","__gptrput");
11338         break;                  
11339     }
11340 }
11341 /*-----------------------------------------------------------------*/
11342 /* genDataPointerSet - remat pointer to data space                 */
11343 /*-----------------------------------------------------------------*/
11344 static void genDataPointerSet(operand *right,
11345                               operand *result,
11346                               iCode *ic)
11347 {
11348     int size, offset = 0, resoffset=0 ;
11349
11350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11351     pic16_aopOp(right,ic,FALSE);
11352
11353     size = AOP_SIZE(right);
11354
11355 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11356
11357 #if 0
11358     if ( AOP_TYPE(result) == AOP_PCODE) {
11359       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11360               AOP(result)->aopu.pcop->name,
11361                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11362               PCOR(AOP(result)->aopu.pcop)->instance:
11363               PCOI(AOP(result)->aopu.pcop)->offset);
11364     }
11365 #endif
11366
11367         if(AOP(result)->aopu.pcop->type == PO_DIR)
11368                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11369
11370         while (size--) {
11371                 if (AOP_TYPE(right) == AOP_LIT) {
11372                   unsigned int lit;
11373
11374                     if(!IS_FLOAT(operandType( right )))
11375                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11376                     else {
11377                       union {
11378                         unsigned long lit_int;
11379                         float lit_float;
11380                       } info;
11381         
11382                         /* take care if literal is a float */
11383                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11384                         lit = info.lit_int;
11385                     }
11386
11387                     lit = lit >> (8*offset);
11388                     if(lit&0xff) {
11389                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11390                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11391                     } else {
11392                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11393                     }
11394                 } else {
11395                   mov2w(AOP(right), offset);
11396                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11397                 }
11398                 offset++;
11399                 resoffset++;
11400         }
11401
11402     pic16_freeAsmop(right,NULL,ic,TRUE);
11403 }
11404
11405
11406
11407 /*-----------------------------------------------------------------*/
11408 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11409 /*-----------------------------------------------------------------*/
11410 static void genNearPointerSet (operand *right,
11411                                operand *result, 
11412                                iCode *ic)
11413 {
11414   asmop *aop = NULL;
11415   char *l;
11416   sym_link *retype;
11417   sym_link *ptype = operandType(result);
11418   sym_link *resetype;
11419     
11420         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11421         retype= getSpec(operandType(right));
11422         resetype = getSpec(operandType(result));
11423   
11424         pic16_aopOp(result,ic,FALSE);
11425     
11426         /* if the result is rematerializable &
11427          * in data space & not a bit variable */
11428         
11429         /* and result is not a bit variable */
11430         if (AOP_TYPE(result) == AOP_PCODE
11431 //              && AOP_TYPE(result) == AOP_IMMD
11432                 && DCL_TYPE(ptype) == POINTER
11433                 && !IS_BITFIELD(retype)
11434                 && !IS_BITFIELD(resetype)) {
11435
11436                 genDataPointerSet (right,result,ic);
11437                 pic16_freeAsmop(result,NULL,ic,TRUE);
11438           return;
11439         }
11440
11441         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11442         pic16_aopOp(right,ic,FALSE);
11443         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11444
11445         /* if the value is already in a pointer register
11446          * then don't need anything more */
11447         if (!AOP_INPREG(AOP(result))) {
11448                 /* otherwise get a free pointer register */
11449                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11450
11451 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11452 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11453 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11454                 if(is_LitAOp( AOP(result) ))
11455                 {
11456                   if(!IS_BITFIELD(resetype))
11457                         pic16_loadFSR0( result );  // patch 10
11458                 } else {
11459                   if(!IS_BITFIELD(resetype)) {
11460                         // set up FSR0 with address of result
11461                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11462                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11463                   }
11464                 }
11465
11466         }
11467 //      else
11468 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11469
11470         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11471
11472 //      pic16_loadFSR0( result );
11473
11474         /* if bitfield then unpack the bits */
11475         if (IS_BITFIELD(resetype)) {
11476                 genPackBits (resetype, result, right, NULL, POINTER);
11477         } else {
11478                 /* we have can just get the values */
11479           int size = AOP_SIZE(right);
11480           int offset = 0 ;    
11481
11482                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11483                 while (size--) {
11484                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11485                         if (*l == '@' ) {
11486                                 //MOVA(l);
11487                                 //pic16_emitcode("mov","@%s,a",rname);
11488                                 pic16_emitcode("movf","indf0,w ;1");
11489                         } else {
11490
11491                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11492                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11493                                         if (size) {                                                                     // 
11494                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11495                                         } else {                                                                        // 
11496                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11497                                         }                                                                               // 
11498                                 } else { // no literal                                                                  // 
11499                                         if(size) {                                                                      // 
11500                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11501                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11502                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11503                                         } else {                                                                        // 
11504                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11505                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11506                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11507                                         }                                                                               //
11508                                 }                                                                                       // patch 10
11509                         }
11510                         offset++;
11511                 }
11512         }
11513
11514         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11515         /* now some housekeeping stuff */
11516         if (aop) {
11517                 /* we had to allocate for this iCode */
11518                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11519         } else { 
11520                 /* we did not allocate which means left
11521                  * already in a pointer register, then
11522                  * if size > 0 && this could be used again
11523                  * we have to point it back to where it 
11524                  * belongs */
11525                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11526                 if (AOP_SIZE(right) > 1
11527                         && !OP_SYMBOL(result)->remat
11528                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11529                                 || ic->depth )) {
11530
11531                   int size = AOP_SIZE(right) - 1;
11532
11533                         while (size--)
11534                                 pic16_emitcode("decf","fsr0,f");
11535                         //pic16_emitcode("dec","%s",rname);
11536                 }
11537         }
11538
11539         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11540         /* done */
11541 //release:
11542         pic16_freeAsmop(right,NULL,ic,TRUE);
11543         pic16_freeAsmop(result,NULL,ic,TRUE);
11544 }
11545
11546 /*-----------------------------------------------------------------*/
11547 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11548 /*-----------------------------------------------------------------*/
11549 static void genPagedPointerSet (operand *right,
11550                                operand *result, 
11551                                iCode *ic)
11552 {
11553     asmop *aop = NULL;
11554     regs *preg = NULL ;
11555     char *rname , *l;
11556     sym_link *retype;
11557        
11558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11559
11560     retype= getSpec(operandType(right));
11561     
11562     pic16_aopOp(result,ic,FALSE);
11563     
11564     /* if the value is already in a pointer register
11565        then don't need anything more */
11566     if (!AOP_INPREG(AOP(result))) {
11567         /* otherwise get a free pointer register */
11568         aop = newAsmop(0);
11569         preg = getFreePtr(ic,&aop,FALSE);
11570         pic16_emitcode("mov","%s,%s",
11571                 preg->name,
11572                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11573         rname = preg->name ;
11574     } else
11575         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11576     
11577     pic16_freeAsmop(result,NULL,ic,TRUE);
11578     pic16_aopOp (right,ic,FALSE);
11579
11580     /* if bitfield then unpack the bits */
11581     if (IS_BITFIELD(retype)) 
11582         genPackBits (retype,result,right,rname,PPOINTER);
11583     else {
11584         /* we have can just get the values */
11585         int size = AOP_SIZE(right);
11586         int offset = 0 ;        
11587         
11588         while (size--) {
11589             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11590             
11591             MOVA(l);
11592             pic16_emitcode("movx","@%s,a",rname);
11593
11594             if (size)
11595                 pic16_emitcode("inc","%s",rname);
11596
11597             offset++;
11598         }
11599     }
11600     
11601     /* now some housekeeping stuff */
11602     if (aop) {
11603         /* we had to allocate for this iCode */
11604         pic16_freeAsmop(NULL,aop,ic,TRUE);
11605     } else { 
11606         /* we did not allocate which means left
11607            already in a pointer register, then
11608            if size > 0 && this could be used again
11609            we have to point it back to where it 
11610            belongs */
11611         if (AOP_SIZE(right) > 1 &&
11612             !OP_SYMBOL(result)->remat &&
11613             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11614               ic->depth )) {
11615             int size = AOP_SIZE(right) - 1;
11616             while (size--)
11617                 pic16_emitcode("dec","%s",rname);
11618         }
11619     }
11620
11621     /* done */
11622     pic16_freeAsmop(right,NULL,ic,TRUE);
11623     
11624         
11625 }
11626
11627 /*-----------------------------------------------------------------*/
11628 /* genFarPointerSet - set value from far space                     */
11629 /*-----------------------------------------------------------------*/
11630 static void genFarPointerSet (operand *right,
11631                               operand *result, iCode *ic)
11632 {
11633     int size, offset ;
11634     sym_link *retype = getSpec(operandType(right));
11635
11636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11637     pic16_aopOp(result,ic,FALSE);
11638
11639     /* if the operand is already in dptr 
11640     then we do nothing else we move the value to dptr */
11641     if (AOP_TYPE(result) != AOP_STR) {
11642         /* if this is remateriazable */
11643         if (AOP_TYPE(result) == AOP_IMMD)
11644             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11645         else { /* we need to get it byte by byte */
11646             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11647             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11648             if (options.model == MODEL_FLAT24)
11649             {
11650                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11651             }
11652         }
11653     }
11654     /* so dptr know contains the address */
11655     pic16_freeAsmop(result,NULL,ic,TRUE);
11656     pic16_aopOp(right,ic,FALSE);
11657
11658     /* if bit then unpack */
11659     if (IS_BITFIELD(retype)) 
11660         genPackBits(retype,result,right,"dptr",FPOINTER);
11661     else {
11662         size = AOP_SIZE(right);
11663         offset = 0 ;
11664
11665         while (size--) {
11666             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11667             MOVA(l);
11668             pic16_emitcode("movx","@dptr,a");
11669             if (size)
11670                 pic16_emitcode("inc","dptr");
11671         }
11672     }
11673
11674     pic16_freeAsmop(right,NULL,ic,TRUE);
11675 }
11676
11677 /*-----------------------------------------------------------------*/
11678 /* genGenPointerSet - set value from generic pointer space         */
11679 /*-----------------------------------------------------------------*/
11680 #if 0
11681 static void genGenPointerSet (operand *right,
11682                               operand *result, iCode *ic)
11683 {
11684         int i, size, offset, lit;
11685         sym_link *retype = getSpec(operandType(right));
11686
11687         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11688
11689         pic16_aopOp(result,ic,FALSE);
11690         pic16_aopOp(right,ic,FALSE);
11691         size = AOP_SIZE(right);
11692         offset = 0;
11693
11694         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11695
11696         /* if the operand is already in dptr 
11697                 then we do nothing else we move the value to dptr */
11698         if (AOP_TYPE(result) != AOP_STR) {
11699                 /* if this is remateriazable */
11700                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11701                 // WARNING: anythig until "else" is untested!
11702                 if (AOP_TYPE(result) == AOP_IMMD) {
11703                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11704                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11705                         // load FSR0 from immediate
11706                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11707                         offset = 0;
11708                         while(size--) {
11709                                 if(size) {
11710                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11711                                 } else {
11712                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11713                                 }
11714                                 offset++;
11715                         }
11716                         goto release;
11717                 }
11718                 else { /* we need to get it byte by byte */
11719                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11720                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11721
11722                         // set up FSR0 with address of result
11723                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11724                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11725
11726                         /* hack hack! see if this the FSR. If so don't load W */
11727                         if(AOP_TYPE(right) != AOP_ACC) {
11728
11729                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11730
11731                                 if(AOP_TYPE(right) == AOP_LIT)
11732                                 {
11733                                         // copy literal
11734                                         // note: pic16_popGet handles sign extension
11735                                         for(i=0;i<size;i++) {
11736                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11737                                                 if(i < size-1)
11738                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11739                                                 else
11740                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11741                                         }
11742                                 } else {
11743                                         // copy regs
11744
11745                                         for(i=0;i<size;i++) {
11746                                                 if(i < size-1)
11747                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11748                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11749                                                 else
11750                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11751                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11752                                         }
11753                                 }
11754                                 goto release;
11755                         } 
11756                         // right = ACC
11757                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11758                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11759                         goto release;
11760         } // if (AOP_TYPE(result) != AOP_IMMD)
11761
11762         } // if (AOP_TYPE(result) != AOP_STR)
11763         /* so dptr know contains the address */
11764
11765
11766         /* if bit then unpack */
11767         if (IS_BITFIELD(retype)) 
11768                 genPackBits(retype,result,right,"dptr",GPOINTER);
11769         else {
11770                 size = AOP_SIZE(right);
11771                 offset = 0 ;
11772
11773                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11774
11775                 // set up FSR0 with address of result
11776                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11777                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11778         
11779                 while (size--) {
11780                         if (AOP_TYPE(right) == AOP_LIT) {
11781                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11782                                 if (size) {
11783                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11784                                 } else {
11785                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11786                                 }
11787                         } else { // no literal
11788                                 if(size) {
11789                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11790                                 } else {
11791                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11792                                 }
11793                         }
11794                         offset++;
11795                 }
11796         }
11797
11798         release:
11799         pic16_freeAsmop(right,NULL,ic,TRUE);
11800         pic16_freeAsmop(result,NULL,ic,TRUE);
11801 }
11802 #endif
11803
11804 static void genGenPointerSet (operand *right,
11805                               operand *result, iCode *ic)
11806 {
11807   int size;
11808   sym_link *retype = getSpec(operandType(right));
11809   char fgptrput[32];
11810
11811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11812
11813     pic16_aopOp(result,ic,FALSE);
11814     pic16_aopOp(right,ic,FALSE);
11815     size = AOP_SIZE(right);
11816
11817     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11818
11819
11820     /* if bit then unpack */
11821     if (IS_BITFIELD(retype)) {
11822 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11823       genPackBits(retype,result,right,"dptr",GPOINTER);
11824       goto release;
11825     }
11826
11827     size = AOP_SIZE(right);
11828
11829     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11830
11831
11832
11833     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11834
11835     /* value of right+0 is placed on stack, which will be retrieved
11836      * by the support function this restoring the stack. The important
11837      * thing is that there is no need to manually restore stack pointer
11838      * here */
11839     pushaop(AOP(right), 0);
11840 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11841     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11842     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11843     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11844     
11845     /* load address to write to in WREG:FSR0H:FSR0L */
11846     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11847                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11848     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11849                                 pic16_popCopyReg(&pic16_pc_prodl)));
11850     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11851     
11852
11853     /* put code here */
11854     switch (size) {
11855       case 1: strcpy(fgptrput, "__gptrput1"); break;
11856       case 2: strcpy(fgptrput, "__gptrput2"); break;
11857       case 3: strcpy(fgptrput, "__gptrput3"); break;
11858       case 4: strcpy(fgptrput, "__gptrput4"); break;
11859       default:
11860         werror(W_POSSBUG2, __FILE__, __LINE__);
11861         abort();
11862     }
11863     
11864     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11865     
11866     {
11867       symbol *sym;
11868                   
11869         sym = newSymbol( fgptrput, 0 );
11870         strcpy(sym->rname, fgptrput);
11871         checkAddSym(&externs, sym);
11872     }
11873
11874 release:
11875     pic16_freeAsmop(right,NULL,ic,TRUE);
11876     pic16_freeAsmop(result,NULL,ic,TRUE);
11877 }
11878
11879 /*-----------------------------------------------------------------*/
11880 /* genPointerSet - stores the value into a pointer location        */
11881 /*-----------------------------------------------------------------*/
11882 static void genPointerSet (iCode *ic)
11883 {    
11884     operand *right, *result ;
11885     sym_link *type, *etype;
11886     int p_type;
11887
11888     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11889
11890     right = IC_RIGHT(ic);
11891     result = IC_RESULT(ic) ;
11892
11893     /* depending on the type of pointer we need to
11894     move it to the correct pointer register */
11895     type = operandType(result);
11896     etype = getSpec(type);
11897     /* if left is of type of pointer then it is simple */
11898     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11899         p_type = DCL_TYPE(type);
11900     }
11901     else {
11902         /* we have to go by the storage class */
11903         p_type = PTR_TYPE(SPEC_OCLS(etype));
11904
11905 /*      if (SPEC_OCLS(etype)->codesp ) { */
11906 /*          p_type = CPOINTER ;  */
11907 /*      } */
11908 /*      else */
11909 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11910 /*              p_type = FPOINTER ; */
11911 /*          else */
11912 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11913 /*                  p_type = PPOINTER ; */
11914 /*              else */
11915 /*                  if (SPEC_OCLS(etype) == idata ) */
11916 /*                      p_type = IPOINTER ; */
11917 /*                  else */
11918 /*                      p_type = POINTER ; */
11919     }
11920
11921     /* now that we have the pointer type we assign
11922     the pointer values */
11923     switch (p_type) {
11924
11925     case POINTER:
11926     case IPOINTER:
11927         genNearPointerSet (right,result,ic);
11928         break;
11929
11930     case PPOINTER:
11931         genPagedPointerSet (right,result,ic);
11932         break;
11933
11934     case FPOINTER:
11935         genFarPointerSet (right,result,ic);
11936         break;
11937
11938     case GPOINTER:
11939         genGenPointerSet (right,result,ic);
11940         break;
11941
11942     default:
11943       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11944               "genPointerSet: illegal pointer type");
11945     }
11946 }
11947
11948 /*-----------------------------------------------------------------*/
11949 /* genIfx - generate code for Ifx statement                        */
11950 /*-----------------------------------------------------------------*/
11951 static void genIfx (iCode *ic, iCode *popIc)
11952 {
11953   operand *cond = IC_COND(ic);
11954   int isbit =0;
11955
11956   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11957
11958   pic16_aopOp(cond,ic,FALSE);
11959
11960   /* get the value into acc */
11961   if (AOP_TYPE(cond) != AOP_CRY)
11962     pic16_toBoolean(cond);
11963   else
11964     isbit = 1;
11965   /* the result is now in the accumulator */
11966   pic16_freeAsmop(cond,NULL,ic,TRUE);
11967
11968   /* if there was something to be popped then do it */
11969   if (popIc)
11970     genIpop(popIc);
11971
11972   /* if the condition is  a bit variable */
11973   if (isbit && IS_ITEMP(cond) && 
11974       SPIL_LOC(cond)) {
11975     genIfxJump(ic,SPIL_LOC(cond)->rname);
11976     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11977   }
11978   else {
11979     if (isbit && !IS_ITEMP(cond))
11980       genIfxJump(ic,OP_SYMBOL(cond)->rname);
11981     else
11982       genIfxJump(ic,"a");
11983   }
11984   ic->generated = 1;
11985
11986 }
11987
11988 /*-----------------------------------------------------------------*/
11989 /* genAddrOf - generates code for address of                       */
11990 /*-----------------------------------------------------------------*/
11991 static void genAddrOf (iCode *ic)
11992 {
11993   operand *result, *left;
11994   int size;
11995   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
11996   pCodeOp *pcop0, *pcop1, *pcop2;
11997
11998     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11999
12000     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12001
12002     sym = OP_SYMBOL( IC_LEFT(ic) );
12003     
12004     if(sym->onStack) {
12005       /* get address of symbol on stack */
12006       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12007 #if 0
12008       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12009                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12010 #endif
12011
12012       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12013                       pic16_popCopyReg(&pic16_pc_fsr2l),
12014                       pic16_popGet(AOP(result), 0)));
12015       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12016                       pic16_popCopyReg(&pic16_pc_fsr2h),
12017                       pic16_popGet(AOP(result), 1)));
12018       
12019       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
12020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
12021       emitSKPNC;
12022       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
12023
12024       goto release;
12025     }
12026         
12027 //      if(pic16_debug_verbose) {
12028 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12029 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12030 //      }
12031         
12032     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12033     size = AOP_SIZE(IC_RESULT(ic));
12034
12035
12036     /* Assume that what we want the address of is in data space
12037      * since there is no stack on the PIC, yet! -- VR */
12038   
12039     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12040     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12041     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12042         
12043     if (size == 3) {
12044       pic16_emitpcode(POC_MOVLW, pcop0);
12045       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12046       pic16_emitpcode(POC_MOVLW, pcop1);
12047       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12048       pic16_emitpcode(POC_MOVLW, pcop2);
12049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12050     } else
12051     if (size == 2) {
12052       pic16_emitpcode(POC_MOVLW, pcop0);
12053       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12054       pic16_emitpcode(POC_MOVLW, pcop1);
12055     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12056     } else {
12057       pic16_emitpcode(POC_MOVLW, pcop0);
12058       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12059     }
12060
12061     pic16_freeAsmop(left, NULL, ic, FALSE);
12062 release:
12063     pic16_freeAsmop(result,NULL,ic,TRUE);
12064 }
12065
12066
12067 #if 0
12068 /*-----------------------------------------------------------------*/
12069 /* genFarFarAssign - assignment when both are in far space         */
12070 /*-----------------------------------------------------------------*/
12071 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12072 {
12073     int size = AOP_SIZE(right);
12074     int offset = 0;
12075     char *l ;
12076     /* first push the right side on to the stack */
12077     while (size--) {
12078         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12079         MOVA(l);
12080         pic16_emitcode ("push","acc");
12081     }
12082     
12083     pic16_freeAsmop(right,NULL,ic,FALSE);
12084     /* now assign DPTR to result */
12085     pic16_aopOp(result,ic,FALSE);
12086     size = AOP_SIZE(result);
12087     while (size--) {
12088         pic16_emitcode ("pop","acc");
12089         pic16_aopPut(AOP(result),"a",--offset);
12090     }
12091     pic16_freeAsmop(result,NULL,ic,FALSE);
12092         
12093 }
12094 #endif
12095
12096 /*-----------------------------------------------------------------*/
12097 /* genAssign - generate code for assignment                        */
12098 /*-----------------------------------------------------------------*/
12099 static void genAssign (iCode *ic)
12100 {
12101   operand *result, *right;
12102   int size, offset,know_W;
12103   unsigned long lit = 0L;
12104
12105   result = IC_RESULT(ic);
12106   right  = IC_RIGHT(ic) ;
12107
12108   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12109   
12110   /* if they are the same */
12111   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12112     return ;
12113
12114   /* reversed order operands are aopOp'ed so that result operand
12115    * is effective in case right is a stack symbol. This maneauver
12116    * allows to use the _G.resDirect flag later */
12117   pic16_aopOp(result,ic,TRUE);
12118   pic16_aopOp(right,ic,FALSE);
12119
12120   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12121
12122   /* if they are the same registers */
12123   if (pic16_sameRegs(AOP(right),AOP(result)))
12124     goto release;
12125
12126   /* if the result is a bit */
12127   if (AOP_TYPE(result) == AOP_CRY) {
12128     /* if the right size is a literal then
12129        we know what the value is */
12130     if (AOP_TYPE(right) == AOP_LIT) {
12131           
12132       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12133                   pic16_popGet(AOP(result),0));
12134
12135       if (((int) operandLitValue(right))) 
12136         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12137                        AOP(result)->aopu.aop_dir,
12138                        AOP(result)->aopu.aop_dir);
12139       else
12140         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12141                        AOP(result)->aopu.aop_dir,
12142                        AOP(result)->aopu.aop_dir);
12143       goto release;
12144     }
12145
12146     /* the right is also a bit variable */
12147     if (AOP_TYPE(right) == AOP_CRY) {
12148       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12149       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12150       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12151
12152       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12153                      AOP(result)->aopu.aop_dir,
12154                      AOP(result)->aopu.aop_dir);
12155       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12156                      AOP(right)->aopu.aop_dir,
12157                      AOP(right)->aopu.aop_dir);
12158       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12159                      AOP(result)->aopu.aop_dir,
12160                      AOP(result)->aopu.aop_dir);
12161       goto release ;
12162     }
12163
12164     /* we need to or */
12165     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12166     pic16_toBoolean(right);
12167     emitSKPZ;
12168     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12169     //pic16_aopPut(AOP(result),"a",0);
12170     goto release ;
12171   }
12172
12173   /* bit variables done */
12174   /* general case */
12175   size = AOP_SIZE(result);
12176   offset = 0 ;
12177
12178   if(AOP_TYPE(right) == AOP_LIT) {
12179         if(!IS_FLOAT(operandType( right )))
12180                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12181         else {
12182            union {
12183               unsigned long lit_int;
12184               float lit_float;
12185             } info;
12186         
12187                 /* take care if literal is a float */
12188                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12189                 lit = info.lit_int;
12190         }
12191   }
12192
12193 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12194 //                      sizeof(unsigned long int), sizeof(float));
12195
12196   if(AOP_TYPE(right) != AOP_LIT
12197         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12198         && !IS_FUNC(OP_SYM_TYPE(right))
12199         ) {
12200         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12201 //      fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12202
12203         // set up table pointer
12204         if( (AOP_TYPE(right) == AOP_PCODE)
12205                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
12206 //              || (AOP(right)->aopu.pcop->type == PO_DIR)
12207                 )
12208                 )
12209         {
12210 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12211                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12212                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12213                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12214                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12215                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12216                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12217         } else {
12218 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12219                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12220                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12221                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12222                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12223                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12224                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12225         }
12226
12227         size = min(AOP_SIZE(right), AOP_SIZE(result));
12228         while(size--) {
12229                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12230                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12231                         pic16_popGet(AOP(result),offset)));
12232                 offset++;
12233         }
12234
12235         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12236                 size = AOP_SIZE(result) - AOP_SIZE(right);
12237                 while(size--) {
12238                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12239                         offset++;
12240                 }
12241         }
12242         goto release;
12243   }
12244
12245
12246
12247 #if 0
12248 /* VR - What is this?! */
12249   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12251     if(aopIdx(AOP(result),0) == 4) {
12252
12253       /* this is a workaround to save value of right into wreg too,
12254        * value of wreg is going to be used later */
12255       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12256       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12257       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12258       goto release;
12259     } else
12260 //      assert(0);
12261       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12262   }
12263 #endif
12264
12265   know_W=-1;
12266   while (size--) {
12267   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12268     if(AOP_TYPE(right) == AOP_LIT) {
12269       if(lit&0xff) {
12270         if(know_W != (lit&0xff))
12271           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12272         know_W = lit&0xff;
12273         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12274       } else
12275         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12276
12277       lit >>= 8;
12278
12279     } else if (AOP_TYPE(right) == AOP_CRY) {
12280       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12281       if(offset == 0) {
12282 //        debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12283         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
12284         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12285       }
12286     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12287         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12288         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12289     } else {
12290       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12291
12292       if(!_G.resDirect)         /* use this aopForSym feature */
12293         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12294     }
12295             
12296     offset++;
12297   }
12298   
12299  release:
12300   pic16_freeAsmop (right,NULL,ic,FALSE);
12301   pic16_freeAsmop (result,NULL,ic,TRUE);
12302 }   
12303
12304 /*-----------------------------------------------------------------*/
12305 /* genJumpTab - generates code for jump table                       */
12306 /*-----------------------------------------------------------------*/
12307 static void genJumpTab (iCode *ic)
12308 {
12309     symbol *jtab;
12310     char *l;
12311     pCodeOp *jt_offs;
12312     pCodeOp *jt_offs_hi;
12313     pCodeOp *jt_label;
12314
12315     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12316
12317     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12318     /* get the condition into accumulator */
12319     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12320     MOVA(l);
12321     /* multiply by three */
12322     pic16_emitcode("add","a,acc");
12323     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12324
12325     jtab = newiTempLabel(NULL);
12326     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12327     pic16_emitcode("jmp","@a+dptr");
12328     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12329
12330 #if 0
12331     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12332     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12333     emitSKPNC;
12334     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12335     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12336     pic16_emitpLabel(jtab->key);
12337
12338 #else
12339
12340     jt_offs = pic16_popGetTempReg(0);
12341     jt_offs_hi = pic16_popGetTempReg(1);
12342     jt_label = pic16_popGetLabel (jtab->key);
12343     //fprintf (stderr, "Creating jump table...\n");
12344
12345     // calculate offset into jump table (idx * sizeof (GOTO))
12346     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12347     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12348     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12349     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12350     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12351     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12352     pic16_emitpcode(POC_MOVWF , jt_offs);
12353
12354     // prepare PCLATx (set to first entry in jump table)
12355     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12356     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12357     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12358     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12359     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12360
12361     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12362     pic16_emitpcode(POC_ADDWF , jt_offs);
12363     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12364     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12365     emitSKPNC;
12366     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12367
12368     // release temporaries and prepare jump into table (new PCL --> WREG)
12369     pic16_emitpcode(POC_MOVFW , jt_offs);
12370     pic16_popReleaseTempReg (jt_offs_hi, 1);
12371     pic16_popReleaseTempReg (jt_offs, 0);
12372
12373     // jump into the table
12374     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12375
12376     pic16_emitpLabelFORCE(jtab->key);
12377
12378 #endif
12379     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12380
12381     /* now generate the jump labels */
12382     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12383          jtab = setNextItem(IC_JTLABELS(ic))) {
12384 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12385         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12386         
12387     }
12388
12389 }
12390
12391 /*-----------------------------------------------------------------*/
12392 /* genMixedOperation - gen code for operators between mixed types  */
12393 /*-----------------------------------------------------------------*/
12394 /*
12395   TSD - Written for the PIC port - but this unfortunately is buggy.
12396   This routine is good in that it is able to efficiently promote 
12397   types to different (larger) sizes. Unfortunately, the temporary
12398   variables that are optimized out by this routine are sometimes
12399   used in other places. So until I know how to really parse the 
12400   iCode tree, I'm going to not be using this routine :(.
12401 */
12402 static int genMixedOperation (iCode *ic)
12403 {
12404 #if 0
12405   operand *result = IC_RESULT(ic);
12406   sym_link *ctype = operandType(IC_LEFT(ic));
12407   operand *right = IC_RIGHT(ic);
12408   int ret = 0;
12409   int big,small;
12410   int offset;
12411
12412   iCode *nextic;
12413   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12414
12415   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12416
12417   nextic = ic->next;
12418   if(!nextic)
12419     return 0;
12420
12421   nextright = IC_RIGHT(nextic);
12422   nextleft  = IC_LEFT(nextic);
12423   nextresult = IC_RESULT(nextic);
12424
12425   pic16_aopOp(right,ic,FALSE);
12426   pic16_aopOp(result,ic,FALSE);
12427   pic16_aopOp(nextright,  nextic, FALSE);
12428   pic16_aopOp(nextleft,   nextic, FALSE);
12429   pic16_aopOp(nextresult, nextic, FALSE);
12430
12431   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12432
12433     operand *t = right;
12434     right = nextright;
12435     nextright = t; 
12436
12437     pic16_emitcode(";remove right +","");
12438
12439   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12440 /*
12441     operand *t = right;
12442     right = nextleft;
12443     nextleft = t; 
12444 */
12445     pic16_emitcode(";remove left +","");
12446   } else
12447     return 0;
12448
12449   big = AOP_SIZE(nextleft);
12450   small = AOP_SIZE(nextright);
12451
12452   switch(nextic->op) {
12453
12454   case '+':
12455     pic16_emitcode(";optimize a +","");
12456     /* if unsigned or not an integral type */
12457     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12458       pic16_emitcode(";add a bit to something","");
12459     } else {
12460
12461       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12462
12463       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12464         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12465         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12466       } else
12467         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12468
12469       offset = 0;
12470       while(--big) {
12471
12472         offset++;
12473
12474         if(--small) {
12475           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12476             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12477             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12478           }
12479
12480           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12481           emitSKPNC;
12482           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12483                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12484                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12485           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12486           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12487
12488         } else {
12489           pic16_emitcode("rlf","known_zero,w");
12490
12491           /*
12492             if right is signed
12493               btfsc  right,7
12494                addlw ff
12495           */
12496           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12497             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12498             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12499           } else {
12500             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12501           }
12502         }
12503       }
12504       ret = 1;
12505     }
12506   }
12507   ret = 1;
12508
12509 release:
12510   pic16_freeAsmop(right,NULL,ic,TRUE);
12511   pic16_freeAsmop(result,NULL,ic,TRUE);
12512   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12513   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12514   if(ret)
12515     nextic->generated = 1;
12516
12517   return ret;
12518 #else
12519   return 0;
12520 #endif
12521 }
12522 /*-----------------------------------------------------------------*/
12523 /* genCast - gen code for casting                                  */
12524 /*-----------------------------------------------------------------*/
12525 static void genCast (iCode *ic)
12526 {
12527   operand *result = IC_RESULT(ic);
12528   sym_link *ctype = operandType(IC_LEFT(ic));
12529   sym_link *rtype = operandType(IC_RIGHT(ic));
12530   sym_link *restype = operandType(IC_RESULT(ic));
12531   operand *right = IC_RIGHT(ic);
12532   int size, offset ;
12533
12534         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12535
12536
12537         /* if they are equivalent then do nothing */
12538 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12539 //              return ;
12540
12541         pic16_aopOp(right,ic,FALSE) ;
12542         pic16_aopOp(result,ic,FALSE);
12543
12544         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12545
12546
12547         /* if the result is a bit */
12548         if (AOP_TYPE(result) == AOP_CRY) {
12549         
12550                 /* if the right size is a literal then
12551                  * we know what the value is */
12552                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12553
12554                 if (AOP_TYPE(right) == AOP_LIT) {
12555                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12556                                 pic16_popGet(AOP(result),0));
12557
12558                         if (((int) operandLitValue(right))) 
12559                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12560                                         AOP(result)->aopu.aop_dir,
12561                                         AOP(result)->aopu.aop_dir);
12562                         else
12563                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12564                                         AOP(result)->aopu.aop_dir,
12565                                         AOP(result)->aopu.aop_dir);
12566                         goto release;
12567                 }
12568
12569                 /* the right is also a bit variable */
12570                 if (AOP_TYPE(right) == AOP_CRY) {
12571                         emitCLRC;
12572                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12573
12574                         pic16_emitcode("clrc","");
12575                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12576                                 AOP(right)->aopu.aop_dir,
12577                                 AOP(right)->aopu.aop_dir);
12578                         pic16_aopPut(AOP(result),"c",0);
12579                         goto release ;
12580                 }
12581
12582                 /* we need to or */
12583                 if (AOP_TYPE(right) == AOP_REG) {
12584                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12585                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12586                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12587                 }
12588                 pic16_toBoolean(right);
12589                 pic16_aopPut(AOP(result),"a",0);
12590                 goto release ;
12591         }
12592
12593         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12594           int offset = 1;
12595
12596                 size = AOP_SIZE(result);
12597
12598                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12599
12600                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12601                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12602                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12603
12604                 while (size--)
12605                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12606
12607                 goto release;
12608         }
12609
12610         if(IS_BITFIELD(getSpec(restype))
12611           && IS_BITFIELD(getSpec(rtype))) {
12612           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12613         }
12614
12615         /* if they are the same size : or less */
12616         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12617
12618                 /* if they are in the same place */
12619                 if (pic16_sameRegs(AOP(right),AOP(result)))
12620                         goto release;
12621
12622                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12623 #if 0
12624                 if (IS_PTR_CONST(rtype))
12625 #else
12626                 if (IS_CODEPTR(rtype))
12627 #endif
12628                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12629
12630 #if 0
12631                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12632 #else
12633                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12634 #endif
12635                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12636
12637 #if 0
12638                 if(AOP_TYPE(right) == AOP_IMMD) {
12639                   pCodeOp *pcop0, *pcop1, *pcop2;
12640                   symbol *sym = OP_SYMBOL( right );
12641
12642                         size = AOP_SIZE(result);
12643                         /* low */
12644                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12645                         /* high */
12646                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12647                         /* upper */
12648                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12649         
12650                         if (size == 3) {
12651                                 pic16_emitpcode(POC_MOVLW, pcop0);
12652                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12653                                 pic16_emitpcode(POC_MOVLW, pcop1);
12654                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12655                                 pic16_emitpcode(POC_MOVLW, pcop2);
12656                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12657                         } else
12658                         if (size == 2) {
12659                                 pic16_emitpcode(POC_MOVLW, pcop0);
12660                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12661                                 pic16_emitpcode(POC_MOVLW, pcop1);
12662                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12663                         } else {
12664                                 pic16_emitpcode(POC_MOVLW, pcop0);
12665                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12666                         }
12667                 } else
12668 #endif
12669                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12670                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12671                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12672                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12673                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12674                         if(AOP_SIZE(result) <2)
12675                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12676                 } else {
12677                         /* if they in different places then copy */
12678                         size = AOP_SIZE(result);
12679                         offset = 0 ;
12680                         while (size--) {
12681                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12682                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12683                                 offset++;
12684                         }
12685                 }
12686                 goto release;
12687         }
12688
12689         /* if the result is of type pointer */
12690         if (IS_PTR(ctype)) {
12691           int p_type;
12692           sym_link *type = operandType(right);
12693           sym_link *etype = getSpec(type);
12694
12695                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12696
12697                 /* pointer to generic pointer */
12698                 if (IS_GENPTR(ctype)) {
12699                   char *l = zero;
12700             
12701                         if (IS_PTR(type)) 
12702                                 p_type = DCL_TYPE(type);
12703                         else {
12704                 /* we have to go by the storage class */
12705                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12706
12707 /*              if (SPEC_OCLS(etype)->codesp )  */
12708 /*                  p_type = CPOINTER ;  */
12709 /*              else */
12710 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12711 /*                      p_type = FPOINTER ; */
12712 /*                  else */
12713 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12714 /*                          p_type = PPOINTER; */
12715 /*                      else */
12716 /*                          if (SPEC_OCLS(etype) == idata ) */
12717 /*                              p_type = IPOINTER ; */
12718 /*                          else */
12719 /*                              p_type = POINTER ; */
12720             }
12721                 
12722             /* the first two bytes are known */
12723       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12724             size = GPTRSIZE - 1; 
12725             offset = 0 ;
12726             while (size--) {
12727               if(offset < AOP_SIZE(right)) {
12728                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12729                 mov2f(AOP(result), AOP(right), offset);
12730 /*
12731                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12732                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12733                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12734                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12735                 } else { 
12736                   
12737                   pic16_aopPut(AOP(result),
12738                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12739                          offset);
12740                 }
12741 */
12742               } else 
12743                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12744               offset++;
12745             }
12746             /* the last byte depending on type */
12747             switch (p_type) {
12748             case IPOINTER:
12749             case POINTER:
12750                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12751                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12752 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12753                 break;
12754
12755             case CPOINTER:
12756                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12757                 break;
12758
12759             case FPOINTER:
12760               pic16_emitcode(";BUG!? ","%d",__LINE__);
12761                 l = one;
12762                 break;
12763             case PPOINTER:
12764               pic16_emitcode(";BUG!? ","%d",__LINE__);
12765                 l = "#0x03";
12766                 break;
12767
12768             case GPOINTER:
12769               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12770               break;
12771               
12772             default:
12773                 /* this should never happen */
12774                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12775                        "got unknown pointer type");
12776                 exit(1);
12777             }
12778             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12779             goto release ;
12780         }
12781         
12782         /* just copy the pointers */
12783         size = AOP_SIZE(result);
12784         offset = 0 ;
12785         while (size--) {
12786             pic16_aopPut(AOP(result),
12787                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12788                    offset);
12789             offset++;
12790         }
12791         goto release ;
12792     }
12793     
12794
12795
12796     /* so we now know that the size of destination is greater
12797     than the size of the source.
12798     Now, if the next iCode is an operator then we might be
12799     able to optimize the operation without performing a cast.
12800     */
12801     if(genMixedOperation(ic))
12802       goto release;
12803
12804     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12805     
12806     /* we move to result for the size of source */
12807     size = AOP_SIZE(right);
12808     offset = 0 ;
12809     while (size--) {
12810       mov2f(AOP(result), AOP(right), offset);
12811       offset++;
12812     }
12813
12814     /* now depending on the sign of the destination */
12815     size = AOP_SIZE(result) - AOP_SIZE(right);
12816     /* if unsigned or not an integral type */
12817     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12818       while (size--)
12819         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12820     } else {
12821       /* we need to extend the sign :( */
12822
12823       if(size == 1) {
12824         /* Save one instruction of casting char to int */
12825         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12826         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12827         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12828       } else {
12829         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12830
12831         if(offset)
12832           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12833         else
12834           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12835         
12836         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12837
12838         while (size--)
12839           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12840       }
12841     }
12842
12843 release:
12844     pic16_freeAsmop(right,NULL,ic,TRUE);
12845     pic16_freeAsmop(result,NULL,ic,TRUE);
12846
12847 }
12848
12849 /*-----------------------------------------------------------------*/
12850 /* genDjnz - generate decrement & jump if not zero instrucion      */
12851 /*-----------------------------------------------------------------*/
12852 static int genDjnz (iCode *ic, iCode *ifx)
12853 {
12854     symbol *lbl, *lbl1;
12855     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12856
12857     if (!ifx)
12858         return 0;
12859     
12860     /* if the if condition has a false label
12861        then we cannot save */
12862     if (IC_FALSE(ifx))
12863         return 0;
12864
12865     /* if the minus is not of the form 
12866        a = a - 1 */
12867     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12868         !IS_OP_LITERAL(IC_RIGHT(ic)))
12869         return 0;
12870
12871     if (operandLitValue(IC_RIGHT(ic)) != 1)
12872         return 0;
12873
12874     /* if the size of this greater than one then no
12875        saving */
12876     if (getSize(operandType(IC_RESULT(ic))) > 1)
12877         return 0;
12878
12879     /* otherwise we can save BIG */
12880     lbl = newiTempLabel(NULL);
12881     lbl1= newiTempLabel(NULL);
12882
12883     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12884     
12885     if (IS_AOP_PREG(IC_RESULT(ic))) {
12886         pic16_emitcode("dec","%s",
12887                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12888         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12889         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12890     } else {    
12891
12892
12893       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12894       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12895
12896       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12897       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12898
12899     }
12900     
12901     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12902     ifx->generated = 1;
12903     return 1;
12904 }
12905
12906 /*-----------------------------------------------------------------*/
12907 /* genReceive - generate code for a receive iCode                  */
12908 /*-----------------------------------------------------------------*/
12909 static void genReceive (iCode *ic)
12910 {    
12911   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12912
12913 #if 0
12914   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12915         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12916 #endif
12917 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12918
12919   if (isOperandInFarSpace(IC_RESULT(ic))
12920       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12921           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12922
12923     int size = getSize(operandType(IC_RESULT(ic)));
12924     int offset =  pic16_fReturnSizePic - size;
12925
12926       assert( 0 );
12927       while (size--) {
12928         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12929                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12930                       offset++;
12931         }
12932
12933       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12934
12935       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12936       size = AOP_SIZE(IC_RESULT(ic));
12937       offset = 0;
12938       while (size--) {
12939         pic16_emitcode ("pop","acc");
12940         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12941       }
12942   } else {
12943     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12944
12945     _G.accInUse++;
12946     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12947     _G.accInUse--;
12948     assignResultValue(IC_RESULT(ic), 0);
12949   }
12950
12951   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12952 }
12953
12954 /*-----------------------------------------------------------------*/
12955 /* genDummyRead - generate code for dummy read of volatiles        */
12956 /*-----------------------------------------------------------------*/
12957 static void
12958 genDummyRead (iCode * ic)
12959 {
12960   pic16_emitcode ("; genDummyRead","");
12961   pic16_emitcode ("; not implemented","");
12962
12963   ic = ic;
12964 }
12965
12966 /*-----------------------------------------------------------------*/
12967 /* genpic16Code - generate code for pic16 based controllers        */
12968 /*-----------------------------------------------------------------*/
12969 /*
12970  * At this point, ralloc.c has gone through the iCode and attempted
12971  * to optimize in a way suitable for a PIC. Now we've got to generate
12972  * PIC instructions that correspond to the iCode.
12973  *
12974  * Once the instructions are generated, we'll pass through both the
12975  * peep hole optimizer and the pCode optimizer.
12976  *-----------------------------------------------------------------*/
12977
12978 void genpic16Code (iCode *lic)
12979 {
12980     iCode *ic;
12981     int cln = 0;
12982
12983     lineHead = lineCurr = NULL;
12984
12985     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12986     pic16_addpBlock(pb);
12987
12988 #if 0
12989     /* if debug information required */
12990     if (options.debug && currFunc) {
12991       if (currFunc) {
12992         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12993       }
12994     }
12995 #endif
12996
12997     for (ic = lic ; ic ; ic = ic->next ) {
12998
12999       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13000         if ( cln != ic->lineno ) {
13001             if ( options.debug ) {
13002               debugFile->writeCLine (ic);
13003             }
13004             
13005             if(!options.noCcodeInAsm) {
13006                 pic16_addpCode2pBlock(pb,
13007                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
13008                                 printCLine(ic->filename, ic->lineno)));
13009             }
13010
13011             cln = ic->lineno ;
13012         }
13013         
13014         if(options.iCodeInAsm) {
13015                 char *l;
13016                 /* insert here code to print iCode as comment */
13017                 l = Safe_strdup(printILine(ic));
13018                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13019         }
13020         
13021         /* if the result is marked as
13022            spilt and rematerializable or code for
13023            this has already been generated then
13024            do nothing */
13025         if (resultRemat(ic) || ic->generated ) 
13026             continue ;
13027         
13028         /* depending on the operation */
13029         switch (ic->op) {
13030         case '!' :
13031             pic16_genNot(ic);
13032             break;
13033             
13034         case '~' :
13035             pic16_genCpl(ic);
13036             break;
13037             
13038         case UNARYMINUS:
13039             genUminus (ic);
13040             break;
13041             
13042         case IPUSH:
13043             genIpush (ic);
13044             break;
13045             
13046         case IPOP:
13047             /* IPOP happens only when trying to restore a 
13048                spilt live range, if there is an ifx statement
13049                following this pop then the if statement might
13050                be using some of the registers being popped which
13051                would destroy the contents of the register so
13052                we need to check for this condition and handle it */
13053             if (ic->next            && 
13054                 ic->next->op == IFX &&
13055                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13056                 genIfx (ic->next,ic);
13057             else
13058                 genIpop (ic);
13059             break; 
13060             
13061         case CALL:
13062             genCall (ic);
13063             break;
13064             
13065         case PCALL:
13066             genPcall (ic);
13067             break;
13068             
13069         case FUNCTION:
13070             genFunction (ic);
13071             break;
13072             
13073         case ENDFUNCTION:
13074             genEndFunction (ic);
13075             break;
13076             
13077         case RETURN:
13078             genRet (ic);
13079             break;
13080             
13081         case LABEL:
13082             genLabel (ic);
13083             break;
13084             
13085         case GOTO:
13086             genGoto (ic);
13087             break;
13088             
13089         case '+' :
13090             pic16_genPlus (ic) ;
13091             break;
13092             
13093         case '-' :
13094             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13095                 pic16_genMinus (ic);
13096             break;
13097             
13098         case '*' :
13099             genMult (ic);
13100             break;
13101             
13102         case '/' :
13103             genDiv (ic) ;
13104             break;
13105             
13106         case '%' :
13107             genMod (ic);
13108             break;
13109             
13110         case '>' :
13111             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
13112             break;
13113             
13114         case '<' :
13115             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13116             break;
13117             
13118         case LE_OP:
13119         case GE_OP:
13120         case NE_OP:
13121             
13122             /* note these two are xlated by algebraic equivalence
13123                during parsing SDCC.y */
13124             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13125                    "got '>=' or '<=' shouldn't have come here");
13126             break;      
13127             
13128         case EQ_OP:
13129             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13130             break;          
13131             
13132         case AND_OP:
13133             genAndOp (ic);
13134             break;
13135             
13136         case OR_OP:
13137             genOrOp (ic);
13138             break;
13139             
13140         case '^' :
13141             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13142             break;
13143             
13144         case '|' :
13145                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13146             break;
13147             
13148         case BITWISEAND:
13149             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13150             break;
13151             
13152         case INLINEASM:
13153             genInline (ic);
13154             break;
13155             
13156         case RRC:
13157             genRRC (ic);
13158             break;
13159             
13160         case RLC:
13161             genRLC (ic);
13162             break;
13163             
13164         case GETHBIT:
13165             genGetHbit (ic);
13166             break;
13167             
13168         case LEFT_OP:
13169             genLeftShift (ic);
13170             break;
13171             
13172         case RIGHT_OP:
13173             genRightShift (ic);
13174             break;
13175             
13176         case GET_VALUE_AT_ADDRESS:
13177             genPointerGet(ic);
13178             break;
13179             
13180         case '=' :
13181             if (POINTER_SET(ic))
13182                 genPointerSet(ic);
13183             else
13184                 genAssign(ic);
13185             break;
13186             
13187         case IFX:
13188             genIfx (ic,NULL);
13189             break;
13190             
13191         case ADDRESS_OF:
13192             genAddrOf (ic);
13193             break;
13194             
13195         case JUMPTABLE:
13196             genJumpTab (ic);
13197             break;
13198             
13199         case CAST:
13200             genCast (ic);
13201             break;
13202             
13203         case RECEIVE:
13204             genReceive(ic);
13205             break;
13206             
13207         case SEND:
13208             addSet(&_G.sendSet,ic);
13209             /* create a reversed list of SEND iCodes */
13210 //            addSetHead(&_G.sendSet, ic);
13211             break;
13212
13213         case DUMMY_READ_VOLATILE:
13214           genDummyRead (ic);
13215           break;
13216
13217         default :
13218             ic = ic;
13219         }
13220     }
13221
13222
13223     /* now we are ready to call the
13224        peep hole optimizer */
13225     if (!options.nopeep) {
13226       peepHole (&lineHead);
13227     }
13228     /* now do the actual printing */
13229     printLine (lineHead, codeOutFile);
13230
13231 #ifdef PCODE_DEBUG
13232     DFPRINTF((stderr,"printing pBlock\n\n"));
13233     pic16_printpBlock(stdout,pb);
13234 #endif
13235
13236     return;
13237 }
13238