* as/xa51/xa_version.h,
[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     if(IC_FALSE(ifx)) 
584       DEBUGpic16_emitcode("; ***","ifx false is non-null");
585 #endif
586   }
587
588   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
589
590 }
591 #if 0
592 /*-----------------------------------------------------------------*/
593 /* pointerCode - returns the code for a pointer type               */
594 /*-----------------------------------------------------------------*/
595 static int pointerCode (sym_link *etype)
596 {
597
598     return PTR_TYPE(SPEC_OCLS(etype));
599
600 }
601 #endif
602
603 /*-----------------------------------------------------------------*/
604 /* aopForSym - for a true symbol                                   */
605 /*-----------------------------------------------------------------*/
606 static asmop *aopForSym (iCode *ic, operand *op, bool result)
607 {
608     symbol *sym=OP_SYMBOL(op);
609     asmop *aop;
610     memmap *space= SPEC_OCLS(sym->etype);
611
612     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
613
614     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
615     
616 //    sym = OP_SYMBOL(op);
617
618     /* if already has one */
619     if (sym->aop) {
620             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
621         return sym->aop;
622     }
623
624 #if 0
625     /* if symbol was initially placed onStack then we must re-place it
626      * to direct memory, since pic16 does not have a specific stack */
627     if(sym->onStack) {
628         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
629     }
630 #endif
631
632 #if 1
633     /* assign depending on the storage class */
634     /* if it is on the stack or indirectly addressable */
635     /* space we need to assign either r0 or r1 to it   */    
636     if (sym->onStack || sym->iaccess) {
637       pCodeOp *pcop[4];
638       int i;
639       
640         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
641                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
642         
643         /* acquire a temporary register -- it is saved in function */
644
645         sym->aop = aop = newAsmop(AOP_STA);
646         aop->aopu.stk.stk = sym->stack;
647         aop->size = getSize(sym->type);
648
649
650         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
651         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
652         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
653           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
654           
655           for(i=0;i<aop->size;i++)
656             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
657             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
658         } else
659           for(i=0;i<aop->size;i++) {
660             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
661             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
662           }
663
664
665 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
666
667 #if 1
668         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
669         
670         if(_G.accInUse) {
671                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
672         }
673         
674         for(i=0;i<aop->size;i++) {
675
676           /* initialise for stack access via frame pointer */
677           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
678
679           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
680                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
681         }
682         
683         if(_G.accInUse) {
684                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
685         }
686         
687         return (aop);
688 #endif
689
690 #if 0
691         /* now assign the address of the variable to 
692         the pointer register */
693         if (aop->type != AOP_STK) {
694
695             if (sym->onStack) {
696                     if ( _G.accInUse )
697                         pic16_emitcode("push","acc");
698
699                     pic16_emitcode("mov","a,_bp");
700                     pic16_emitcode("add","a,#0x%02x",
701                              ((sym->stack < 0) ?
702                               ((char)(sym->stack - _G.nRegsSaved )) :
703                               ((char)sym->stack)) & 0xff);
704                     pic16_emitcode("mov","%s,a",
705                              aop->aopu.aop_ptr->name);
706
707                     if ( _G.accInUse )
708                         pic16_emitcode("pop","acc");
709             } else
710                 pic16_emitcode("mov","%s,#%s",
711                          aop->aopu.aop_ptr->name,
712                          sym->rname);
713             aop->paged = space->paged;
714         } else
715             aop->aopu.aop_stk = sym->stack;
716         return aop;
717 #endif
718
719     }
720 #endif
721
722 #if 0
723     if (sym->onStack && options.stack10bit)
724     {
725         /* It's on the 10 bit stack, which is located in
726          * far data space.
727          */
728          
729       //DEBUGpic16_emitcode(";","%d",__LINE__);
730
731         if ( _G.accInUse )
732                 pic16_emitcode("push","acc");
733
734         pic16_emitcode("mov","a,_bp");
735         pic16_emitcode("add","a,#0x%02x",
736                  ((sym->stack < 0) ?
737                    ((char)(sym->stack - _G.nRegsSaved )) :
738                    ((char)sym->stack)) & 0xff);
739         
740         genSetDPTR(1);
741         pic16_emitcode ("mov","dpx1,#0x40");
742         pic16_emitcode ("mov","dph1,#0x00");
743         pic16_emitcode ("mov","dpl1, a");
744         genSetDPTR(0);
745         
746         if ( _G.accInUse )
747             pic16_emitcode("pop","acc");
748             
749         sym->aop = aop = newAsmop(AOP_DPTR2);
750         aop->size = getSize(sym->type); 
751         return aop;
752     }
753 #endif
754
755 #if 0
756     /* special case for a function */
757     if (IS_FUNC(sym->type)) {   
758         sym->aop = aop = newAsmop(AOP_PCODE);
759         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
760         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
761         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
762         PCOI(aop->aopu.pcop)->index = 0;
763         aop->size = FPTRSIZE; 
764         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
765         return aop;
766     }
767 #endif
768
769
770
771     //DEBUGpic16_emitcode(";","%d",__LINE__);
772     /* if in bit space */
773     if (IN_BITSPACE(space)) {
774         sym->aop = aop = newAsmop (AOP_CRY);
775         aop->aopu.aop_dir = sym->rname ;
776         aop->size = getSize(sym->type);
777         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
778         return aop;
779     }
780     /* if it is in direct space */
781     if (IN_DIRSPACE(space)) {
782         sym->aop = aop = newAsmop (AOP_DIR);
783         aop->aopu.aop_dir = sym->rname ;
784         aop->size = getSize(sym->type);
785         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
786         pic16_allocDirReg( IC_LEFT(ic) );
787         return aop;
788     }
789
790
791     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
792         sym->aop = aop = newAsmop (AOP_DIR);
793         aop->aopu.aop_dir = sym->rname ;
794         aop->size = getSize(sym->type);
795         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
796         pic16_allocDirReg( IC_LEFT(ic) );
797         return aop;
798     }
799
800
801     /* only remaining is far space */
802     sym->aop = aop = newAsmop(AOP_PCODE);
803
804 /* change the next if to 1 to revert to good old immediate code */
805         if(IN_CODESPACE(space)) {
806                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
807                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
808                 PCOI(aop->aopu.pcop)->index = 0;
809         } else {
810                 /* try to allocate via direct register */
811                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
812 //              aop->size = getSize( sym->type );
813         }
814
815         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
816                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
817
818 #if 0
819         if(!pic16_allocDirReg (IC_LEFT(ic)))
820                 return NULL;
821 #endif
822
823         if(IN_DIRSPACE( space ))
824                 aop->size = PTRSIZE;
825         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
826                 aop->size = FPTRSIZE;
827         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
828         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
829         else if(sym->onStack) {
830                 aop->size = PTRSIZE;
831         } else {
832                 assert( 0 );
833         }
834
835     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
836
837     /* if it is in code space */
838     if (IN_CODESPACE(space))
839         aop->code = 1;
840
841     return aop;     
842 }
843
844 /*-----------------------------------------------------------------*/
845 /* aopForRemat - rematerialzes an object                           */
846 /*-----------------------------------------------------------------*/
847 static asmop *aopForRemat (operand *op) // x symbol *sym)
848 {
849   symbol *sym = OP_SYMBOL(op);
850   operand *refop;
851   iCode *ic = NULL, *oldic;
852   asmop *aop = newAsmop(AOP_PCODE);
853   int val = 0;
854   int offset = 0;
855   int viaimmd=0;
856
857
858         ic = sym->rematiCode;
859
860         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
861         
862         if(IS_OP_POINTER(op)) {
863                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
864         }
865
866         for (;;) {
867                 oldic = ic;
868
869 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
870         
871                 if (ic->op == '+') {
872                         val += (int) operandLitValue(IC_RIGHT(ic));
873                 } else if (ic->op == '-') {
874                         val -= (int) operandLitValue(IC_RIGHT(ic));
875                 } else
876                         break;
877                 
878                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
879         }
880
881         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
882         refop = IC_LEFT(ic);
883
884         if(!op->isaddr)viaimmd++; else viaimmd=0;
885                 
886 /* set the following if to 1 to revert to good old immediate code */
887         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
888                 || viaimmd) {
889
890                 DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
891
892                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
893
894 #if 0
895                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
896 #else
897                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
898 #endif
899
900                 PCOI(aop->aopu.pcop)->index = val;
901         } else {
902                 DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
903
904                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
905                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
906 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
907         }
908
909
910         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
911                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
912 #if 0
913                 val, IS_PTR_CONST(operandType(op)));
914 #else
915                 val, IS_CODEPTR(operandType(op)));
916 #endif
917
918 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
919
920         pic16_allocDirReg (IC_LEFT(ic));
921
922         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
923                 aop->code = 1;
924
925   return aop;        
926 }
927
928 #if 0
929 static int aopIdx (asmop *aop, int offset)
930 {
931   if(!aop)
932     return -1;
933
934   if(aop->type !=  AOP_REG)
935     return -2;
936         
937   return aop->aopu.aop_reg[offset]->rIdx;
938
939 }
940 #endif
941
942 /*-----------------------------------------------------------------*/
943 /* regsInCommon - two operands have some registers in common       */
944 /*-----------------------------------------------------------------*/
945 static bool regsInCommon (operand *op1, operand *op2)
946 {
947     symbol *sym1, *sym2;
948     int i;
949
950     /* if they have registers in common */
951     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
952         return FALSE ;
953
954     sym1 = OP_SYMBOL(op1);
955     sym2 = OP_SYMBOL(op2);
956
957     if (sym1->nRegs == 0 || sym2->nRegs == 0)
958         return FALSE ;
959
960     for (i = 0 ; i < sym1->nRegs ; i++) {
961         int j;
962         if (!sym1->regs[i])
963             continue ;
964
965         for (j = 0 ; j < sym2->nRegs ;j++ ) {
966             if (!sym2->regs[j])
967                 continue ;
968
969             if (sym2->regs[j] == sym1->regs[i])
970                 return TRUE ;
971         }
972     }
973
974     return FALSE ;
975 }
976
977 /*-----------------------------------------------------------------*/
978 /* operandsEqu - equivalent                                        */
979 /*-----------------------------------------------------------------*/
980 static bool operandsEqu ( operand *op1, operand *op2)
981 {
982     symbol *sym1, *sym2;
983
984     /* if they not symbols */
985     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
986         return FALSE;
987
988     sym1 = OP_SYMBOL(op1);
989     sym2 = OP_SYMBOL(op2);
990
991     /* if both are itemps & one is spilt
992        and the other is not then false */
993     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
994         sym1->isspilt != sym2->isspilt )
995         return FALSE ;
996
997     /* if they are the same */
998     if (sym1 == sym2)
999         return TRUE ;
1000
1001     if (sym1->rname[0] && sym2->rname[0]
1002         && strcmp (sym1->rname, sym2->rname) == 0)
1003         return TRUE;
1004
1005
1006     /* if left is a tmp & right is not */
1007     if (IS_ITEMP(op1)  && 
1008         !IS_ITEMP(op2) &&
1009         sym1->isspilt  &&
1010         (sym1->usl.spillLoc == sym2))
1011         return TRUE;
1012
1013     if (IS_ITEMP(op2)  && 
1014         !IS_ITEMP(op1) &&
1015         sym2->isspilt  &&
1016         sym1->level > 0 &&
1017         (sym2->usl.spillLoc == sym1))
1018         return TRUE ;
1019
1020     return FALSE ;
1021 }
1022
1023 /*-----------------------------------------------------------------*/
1024 /* pic16_sameRegs - two asmops have the same registers                   */
1025 /*-----------------------------------------------------------------*/
1026 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1027 {
1028     int i;
1029
1030     if (aop1 == aop2)
1031         return TRUE ;
1032
1033     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1034                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1035
1036     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1037
1038     if (aop1->type != AOP_REG ||
1039         aop2->type != AOP_REG )
1040         return FALSE ;
1041
1042     if (aop1->size != aop2->size )
1043         return FALSE ;
1044
1045     for (i = 0 ; i < aop1->size ; i++ ) {
1046 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1047
1048 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1049         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1050             return FALSE ;
1051     }
1052
1053     return TRUE ;
1054 }
1055
1056 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1057 {
1058     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1059                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1060
1061     if(aop1 == aop2)return TRUE;
1062     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1063       
1064       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1065     
1066   return TRUE;
1067 }
1068
1069
1070 /*-----------------------------------------------------------------*/
1071 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1072 /*-----------------------------------------------------------------*/
1073 void pic16_aopOp (operand *op, iCode *ic, bool result)
1074 {
1075     asmop *aop;
1076     symbol *sym;
1077     int i;
1078
1079     if (!op)
1080         return ;
1081
1082 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1083
1084     /* if this a literal */
1085     if (IS_OP_LITERAL(op)) {
1086         op->aop = aop = newAsmop(AOP_LIT);
1087         aop->aopu.aop_lit = op->operand.valOperand;
1088         aop->size = getSize(operandType(op));
1089         return;
1090     }
1091
1092     {
1093       sym_link *type = operandType(op);
1094 #if 0
1095       if(IS_PTR_CONST(type))
1096 #else
1097       if(IS_CODEPTR(type))
1098 #endif
1099         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1100     }
1101
1102     /* if already has a asmop then continue */
1103     if (op->aop)
1104         return ;
1105
1106     /* if the underlying symbol has a aop */
1107     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1108       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1109         op->aop = OP_SYMBOL(op)->aop;
1110         return;
1111     }
1112
1113     /* if this is a true symbol */
1114     if (IS_TRUE_SYMOP(op)) {    
1115         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1116       op->aop = aopForSym(ic, op, result);
1117       return ;
1118     }
1119
1120     /* this is a temporary : this has
1121     only four choices :
1122     a) register
1123     b) spillocation
1124     c) rematerialize 
1125     d) conditional   
1126     e) can be a return use only */
1127
1128     sym = OP_SYMBOL(op);
1129
1130         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1131     /* if the type is a conditional */
1132     if (sym->regType == REG_CND) {
1133         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1134         aop->size = 0;
1135         return;
1136     }
1137
1138     /* if it is spilt then two situations
1139     a) is rematerialize 
1140     b) has a spill location */
1141     if (sym->isspilt || sym->nRegs == 0) {
1142
1143       DEBUGpic16_emitcode(";","%d",__LINE__);
1144         /* rematerialize it NOW */
1145         if (sym->remat) {
1146
1147             sym->aop = op->aop = aop = aopForRemat (op);
1148             aop->size = getSize(sym->type);
1149             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1150             return;
1151         }
1152
1153 #if 1
1154         if (sym->accuse) {
1155             int i;
1156             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1157             aop->size = getSize(sym->type);
1158             for ( i = 0 ; i < 1 ; i++ ) {
1159                 aop->aopu.aop_str[i] = accUse[i];
1160 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1161             }
1162             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1163             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1164             return;  
1165         }
1166 #endif
1167
1168 #if 1
1169         if (sym->ruonly ) {
1170           /*
1171           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1172           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1173           //pic16_allocDirReg (IC_LEFT(ic));
1174           aop->size = getSize(sym->type);
1175           */
1176
1177           unsigned i;
1178
1179           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1180           aop->size = getSize(sym->type);
1181           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1182             aop->aopu.aop_str[i] = fReturn[i];
1183
1184           DEBUGpic16_emitcode(";","%d",__LINE__);
1185           return;
1186         }
1187 #endif
1188         /* else spill location  */
1189         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1190             /* force a new aop if sizes differ */
1191             sym->usl.spillLoc->aop = NULL;
1192         }
1193
1194 #if 0
1195         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1196                             __FUNCTION__,__LINE__,
1197                             sym->usl.spillLoc->rname,
1198                             sym->rname, sym->usl.spillLoc->offset);
1199 #endif
1200
1201         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1202         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1203         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1204                                           getSize(sym->type), 
1205                                           sym->usl.spillLoc->offset, op);
1206         aop->size = getSize(sym->type);
1207
1208         return;
1209     }
1210
1211     {
1212       sym_link *type = operandType(op);
1213 #if 0
1214       if(IS_PTR_CONST(type)) 
1215 #else
1216       if(IS_CODEPTR(type)) 
1217 #endif
1218         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1219     }
1220
1221     /* must be in a register */
1222     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1223     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1224     aop->size = sym->nRegs;
1225     for ( i = 0 ; i < sym->nRegs ;i++)
1226         aop->aopu.aop_reg[i] = sym->regs[i];
1227 }
1228
1229 /*-----------------------------------------------------------------*/
1230 /* pic16_freeAsmop - free up the asmop given to an operand               */
1231 /*----------------------------------------------------------------*/
1232 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1233 {   
1234     asmop *aop ;
1235
1236     if (!op)
1237         aop = aaop;
1238     else 
1239         aop = op->aop;
1240
1241     if (!aop)
1242         return ;
1243
1244     if (aop->freed)
1245         goto dealloc; 
1246
1247     aop->freed = 1;
1248
1249     /* depending on the asmop type only three cases need work AOP_RO
1250        , AOP_R1 && AOP_STK */
1251 #if 1
1252     switch (aop->type) {
1253         case AOP_FSR0 :
1254             if (_G.fsr0Pushed ) {
1255                 if (pop) {
1256                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1257                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1258 //                    pic16_emitcode ("pop","ar0");
1259                     _G.fsr0Pushed--;
1260                 }
1261             }
1262             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1263             break;
1264
1265         case AOP_FSR2 :
1266             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1267             break;
1268
1269         case AOP_R0 :
1270             if (_G.r0Pushed ) {
1271                 if (pop) {
1272                     pic16_emitcode ("pop","ar0");     
1273                     _G.r0Pushed--;
1274                 }
1275             }
1276             bitVectUnSetBit(ic->rUsed,R0_IDX);
1277             break;
1278
1279         case AOP_R1 :
1280             if (_G.r1Pushed ) {
1281                 if (pop) {
1282                     pic16_emitcode ("pop","ar1");
1283                     _G.r1Pushed--;
1284                 }
1285             }
1286             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1287             break;
1288
1289         case AOP_STA:
1290           {
1291             int i;
1292
1293               /* we must store the result on stack */
1294               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1295                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1296                 for(i=0;i<aop->size;i++) {
1297                   /* initialise for stack access via frame pointer */
1298                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1299
1300                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1301                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1302                 }
1303         
1304                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1305               }
1306
1307               if(!_G.resDirect) {
1308                 for(i=0;i<aop->size;i++)
1309                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1310               }
1311               _G.resDirect = 0;
1312           }
1313           break;
1314 #if 0
1315         case AOP_STK :
1316         {
1317             int sz = aop->size;    
1318             int stk = aop->aopu.aop_stk + aop->size;
1319             bitVectUnSetBit(ic->rUsed,R0_IDX);
1320             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1321
1322             getFreePtr(ic,&aop,FALSE);
1323             
1324             if (options.stack10bit)
1325             {
1326                 /* I'm not sure what to do here yet... */
1327                 /* #STUB */
1328                 fprintf(stderr, 
1329                         "*** Warning: probably generating bad code for "
1330                         "10 bit stack mode.\n");
1331             }
1332             
1333             if (stk) {
1334                 pic16_emitcode ("mov","a,_bp");
1335                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1336                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1337             } else {
1338                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1339             }
1340
1341             while (sz--) {
1342                 pic16_emitcode("pop","acc");
1343                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1344                 if (!sz) break;
1345                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1346             }
1347             op->aop = aop;
1348             pic16_freeAsmop(op,NULL,ic,TRUE);
1349             if (_G.r0Pushed) {
1350                 pic16_emitcode("pop","ar0");
1351                 _G.r0Pushed--;
1352             }
1353
1354             if (_G.r1Pushed) {
1355                 pic16_emitcode("pop","ar1");
1356                 _G.r1Pushed--;
1357             }       
1358         }
1359 #endif
1360
1361     }
1362 #endif
1363
1364 dealloc:
1365     /* all other cases just dealloc */
1366     if (op ) {
1367         op->aop = NULL;
1368         if (IS_SYMOP(op)) {
1369             OP_SYMBOL(op)->aop = NULL;    
1370             /* if the symbol has a spill */
1371             if (SPIL_LOC(op))
1372                 SPIL_LOC(op)->aop = NULL;
1373         }
1374     }
1375 }
1376
1377 /*-----------------------------------------------------------------*/
1378 /* pic16_aopGet - for fetching value of the aop                          */
1379 /*-----------------------------------------------------------------*/
1380 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1381 {
1382     char *s = buffer ;
1383     char *rs;
1384
1385     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1386
1387     /* offset is greater than size then zero */
1388     if (offset > (aop->size - 1) &&
1389         aop->type != AOP_LIT)
1390         return zero;
1391
1392     /* depending on type */
1393     switch (aop->type) {
1394
1395     case AOP_FSR0:
1396     case AOP_FSR2:
1397       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1398       rs = Safe_calloc(1, strlen(s)+1);
1399       strcpy(rs, s);
1400       return (rs);
1401       
1402 #if 0
1403       /* if we need to increment it */
1404       while (offset > aop->coff)
1405         {
1406           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1407           aop->coff++;
1408         }
1409
1410       while (offset < aop->coff)
1411         {
1412           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1413           aop->coff--;
1414         }
1415       aop->coff = offset;
1416       if (aop->paged)
1417         {
1418           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1419           return (dname ? "acc" : "a");
1420         }
1421       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1422       rs = Safe_calloc (1, strlen (s) + 1);
1423       strcpy (rs, s);
1424       return rs;
1425 #endif
1426
1427         
1428     case AOP_IMMD:
1429         if (bit16) 
1430             sprintf (s,"%s",aop->aopu.aop_immd);
1431         else
1432             if (offset) 
1433                 sprintf(s,"(%s >> %d)",
1434                         aop->aopu.aop_immd,
1435                         offset*8);
1436             else
1437                 sprintf(s,"%s",
1438                         aop->aopu.aop_immd);
1439         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1440         rs = Safe_calloc(1,strlen(s)+1);
1441         strcpy(rs,s);   
1442         return rs;
1443         
1444     case AOP_DIR:
1445       if (offset) {
1446         sprintf(s,"(%s + %d)",
1447                 aop->aopu.aop_dir,
1448                 offset);
1449         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1450       } else
1451             sprintf(s,"%s",aop->aopu.aop_dir);
1452         rs = Safe_calloc(1,strlen(s)+1);
1453         strcpy(rs,s);   
1454         return rs;
1455         
1456     case AOP_REG:
1457       //if (dname) 
1458       //    return aop->aopu.aop_reg[offset]->dname;
1459       //else
1460             return aop->aopu.aop_reg[offset]->name;
1461         
1462     case AOP_CRY:
1463       //pic16_emitcode(";","%d",__LINE__);
1464       return aop->aopu.aop_dir;
1465         
1466     case AOP_ACC:
1467         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1468 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1469 //        assert( 0 );
1470 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1471         rs = Safe_strdup("WREG");
1472         return (rs);
1473
1474     case AOP_LIT:
1475         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1476         rs = Safe_calloc(1,strlen(s)+1);
1477         strcpy(rs,s);   
1478         return rs;
1479         
1480     case AOP_STR:
1481         aop->coff = offset ;
1482         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1483             dname)
1484             return "acc";
1485         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1486         
1487         return aop->aopu.aop_str[offset];
1488         
1489     case AOP_PCODE:
1490       {
1491         pCodeOp *pcop = aop->aopu.pcop;
1492         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1493         if(pcop->name) {
1494           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1495           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1496           sprintf(s,"%s", pcop->name);
1497         } else
1498           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1499
1500       }
1501       rs = Safe_calloc(1,strlen(s)+1);
1502       strcpy(rs,s);   
1503       return rs;
1504
1505     case AOP_STA:
1506         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1507         return (rs);
1508         
1509     case AOP_STK:
1510 //        pCodeOp *pcop = aop->aop
1511         break;
1512
1513     }
1514
1515     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1516     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1517            "aopget got unsupported aop->type");
1518     exit(0);
1519 }
1520
1521
1522
1523 /* lock has the following meaning: When allocating temporary registers
1524  * for stack variables storage, the value of the temporary register is
1525  * saved on stack. Its value is restored at the end. This procedure is
1526  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1527  * a possibility that before a call to pic16_aopOp, a temporary register
1528  * is allocated for a while and it is freed after some time, this will
1529  * mess the stack and values will not be restored properly. So use lock=1
1530  * to allocate temporary registers used internally by the programmer, and
1531  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1532  * to inform the compiler developer about a possible bug. This is an internal
1533  * feature for developing the compiler -- VR */
1534  
1535 int _TempReg_lock = 0;
1536 /*-----------------------------------------------------------------*/
1537 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1538 /*-----------------------------------------------------------------*/
1539 pCodeOp *pic16_popGetTempReg(int lock)
1540 {
1541   pCodeOp *pcop;
1542   symbol *cfunc;
1543
1544 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1545     if(_TempReg_lock) {
1546       werror(W_POSSBUG2, __FILE__, __LINE__);
1547     }
1548     
1549     _TempReg_lock += lock;
1550     
1551     cfunc = currFunc;
1552     currFunc = NULL;
1553
1554     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1555     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1556       PCOR(pcop)->r->wasUsed=1;
1557       PCOR(pcop)->r->isFree=0;
1558
1559       /* push value on stack */
1560       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1561     }
1562
1563     currFunc = cfunc;
1564
1565   return pcop;
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1570 /*                            don't save if inside v               */
1571 /*-----------------------------------------------------------------*/
1572 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1573 {
1574   pCodeOp *pcop;
1575   symbol *cfunc;
1576
1577 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1578
1579     if(_TempReg_lock) {
1580       werror(W_POSSBUG2, __FILE__, __LINE__);
1581     }
1582
1583     _TempReg_lock += lock;
1584
1585     cfunc = currFunc;
1586     currFunc = NULL;
1587
1588     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1589     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1590       PCOR(pcop)->r->wasUsed=1;
1591       PCOR(pcop)->r->isFree=0;
1592
1593       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1594       /* push value on stack */
1595         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1596       }
1597     }
1598
1599     currFunc = cfunc;
1600
1601   return pcop;
1602 }
1603
1604
1605 /*-----------------------------------------------------------------*/
1606 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1607 /*-----------------------------------------------------------------*/
1608 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1609 {
1610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1611
1612   _TempReg_lock -= lock;
1613
1614   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1615     PCOR(pcop)->r->isFree = 1;
1616     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1617   }
1618 }
1619 /*-----------------------------------------------------------------*/
1620 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1621 /*-----------------------------------------------------------------*/
1622 pCodeOp *pic16_popGetLabel(unsigned int key)
1623 {
1624
1625   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1626
1627   if(key>max_key)
1628     max_key = key;
1629
1630   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1631 }
1632
1633 /*-----------------------------------------------------------------*/
1634 /* pic16_popCopyReg - copy a pcode operator                              */
1635 /*-----------------------------------------------------------------*/
1636 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1637 {
1638   pCodeOpReg *pcor;
1639
1640   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1641   pcor->pcop.type = pc->pcop.type;
1642   if(pc->pcop.name) {
1643     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1644       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1645   } else
1646     pcor->pcop.name = NULL;
1647
1648   pcor->r = pc->r;
1649   pcor->rIdx = pc->rIdx;
1650   pcor->r->wasUsed=1;
1651
1652 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1653
1654   return PCOP(pcor);
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1659 /*-----------------------------------------------------------------*/
1660 pCodeOp *pic16_popGetLit(int lit)
1661 {
1662   return pic16_newpCodeOpLit(lit);
1663 }
1664
1665 /*-----------------------------------------------------------------*/
1666 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1667 /*-----------------------------------------------------------------*/
1668 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1669 {
1670   return pic16_newpCodeOpLit2(lit, arg2);
1671 }
1672
1673
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1678 {
1679   return pic16_newpCodeOpImmd(name, offset,index, 0);
1680 }
1681
1682
1683 /*-----------------------------------------------------------------*/
1684 /* pic16_popGet - asm operator to pcode operator conversion              */
1685 /*-----------------------------------------------------------------*/
1686 pCodeOp *pic16_popGetWithString(char *str)
1687 {
1688   pCodeOp *pcop;
1689
1690
1691   if(!str) {
1692     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1693     exit (1);
1694   }
1695
1696   pcop = pic16_newpCodeOp(str,PO_STR);
1697
1698   return pcop;
1699 }
1700
1701 /*-----------------------------------------------------------------*/
1702 /* pic16_popRegFromString -                                        */
1703 /*-----------------------------------------------------------------*/
1704 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1705 {
1706
1707   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1708   pcop->type = PO_DIR;
1709
1710   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1711   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1712
1713   if(!str)
1714     str = "BAD_STRING";
1715
1716   pcop->name = Safe_calloc(1,strlen(str)+1);
1717   strcpy(pcop->name,str);
1718
1719   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1720
1721   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1722
1723   /* make sure that register doesn't exist,
1724    * and operand isn't NULL
1725    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1726   if((PCOR(pcop)->r == NULL) 
1727     && (op)
1728     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1729 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1730 //              __FUNCTION__, __LINE__, str, size, offset);
1731
1732     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1733     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1734
1735   }
1736   PCOR(pcop)->instance = offset;
1737
1738   return pcop;
1739 }
1740
1741 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1742 {
1743   pCodeOp *pcop;
1744
1745 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1746
1747         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1748         PCOR(pcop)->rIdx = rIdx;
1749         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1750
1751         PCOR(pcop)->r->isFree = 0;
1752         PCOR(pcop)->r->wasUsed = 1;
1753
1754         pcop->type = PCOR(pcop)->r->pc_type;
1755
1756   return pcop;
1757 }
1758
1759 /*---------------------------------------------------------------------------------*/
1760 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1761 /*                 VR 030601                                                       */
1762 /*---------------------------------------------------------------------------------*/
1763 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1764 {
1765   pCodeOpReg2 *pcop2;
1766   pCodeOp *temp;
1767   
1768         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1769
1770         /* comment the following check, so errors to throw up */
1771 //      if(!pcop2)return NULL;
1772
1773         temp = pic16_popGet(aop_dst, offset);
1774         pcop2->pcop2 = temp;
1775         
1776   return PCOP(pcop2);
1777 }
1778
1779
1780
1781 /*--------------------------------------------------------------------------------.-*/
1782 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1783 /*                  VR 030601 , adapted by Hans Dorn                                */
1784 /*--------------------------------------------------------------------------------.-*/
1785 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1786 {
1787   pCodeOpReg2 *pcop2;
1788  
1789         pcop2 = (pCodeOpReg2 *)src;
1790         pcop2->pcop2 = dst;
1791         
1792         return PCOP(pcop2);
1793 }
1794
1795
1796
1797 /*---------------------------------------------------------------------------------*/
1798 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1799 /*                     movff instruction                                           */
1800 /*---------------------------------------------------------------------------------*/
1801 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1802 {
1803   pCodeOpReg2 *pcop2;
1804
1805         if(!noalloc) {
1806                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1807                 pcop2->pcop2 = pic16_popCopyReg(dst);
1808         } else {
1809                 /* the pCodeOp may be already allocated */
1810                 pcop2 = (pCodeOpReg2 *)(src);
1811                 pcop2->pcop2 = (pCodeOp *)(dst);
1812         }
1813
1814   return PCOP(pcop2);
1815 }
1816
1817
1818 /*-----------------------------------------------------------------*/
1819 /* pic16_popGet - asm operator to pcode operator conversion              */
1820 /*-----------------------------------------------------------------*/
1821 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1822 {
1823   //char *s = buffer ;
1824   char *rs;
1825   pCodeOp *pcop;
1826
1827     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1828     /* offset is greater than
1829     size then zero */
1830
1831 //    if (offset > (aop->size - 1) &&
1832 //        aop->type != AOP_LIT)
1833 //      return NULL;  //zero;
1834
1835     /* depending on type */
1836     switch (aop->type) {
1837         
1838     case AOP_R0:
1839     case AOP_R1:
1840     case AOP_DPTR:
1841     case AOP_DPTR2:
1842         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1843         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1844         assert( 0 );
1845         return NULL;
1846
1847
1848     case AOP_FSR0:
1849     case AOP_FSR2:
1850       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1851       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1852       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1853       PCOR(pcop)->r->wasUsed = 1;
1854       PCOR(pcop)->r->isFree = 0;
1855       
1856       PCOR(pcop)->instance = offset;
1857       pcop->type = PCOR(pcop)->r->pc_type;
1858       return (pcop);
1859
1860     case AOP_IMMD:
1861       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1862       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1863
1864     case AOP_STA:
1865       /* pCodeOp is already allocated from aopForSym */
1866         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1867         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1868           
1869       return (pcop);
1870       
1871     case AOP_ACC:
1872       {
1873         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1874
1875         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1876
1877         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1878         
1879         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1880         PCOR(pcop)->rIdx = rIdx;
1881         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1882         PCOR(pcop)->r->wasUsed=1;
1883         PCOR(pcop)->r->isFree=0;
1884
1885         PCOR(pcop)->instance = offset;
1886         pcop->type = PCOR(pcop)->r->pc_type;
1887 //      rs = aop->aopu.aop_reg[offset]->name;
1888 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1889         return pcop;
1890
1891
1892 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1893 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1894
1895 //      assert( 0 );
1896       }
1897         
1898     case AOP_DIR:
1899       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1900       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1901         
1902     case AOP_REG:
1903       {
1904         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1905
1906         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1907         
1908         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1909 //      pcop->type = PO_GPR_REGISTER;
1910         PCOR(pcop)->rIdx = rIdx;
1911         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1912         PCOR(pcop)->r->wasUsed=1;
1913         PCOR(pcop)->r->isFree=0;
1914
1915         PCOR(pcop)->instance = offset;
1916         pcop->type = PCOR(pcop)->r->pc_type;
1917         rs = aop->aopu.aop_reg[offset]->name;
1918         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1919         return pcop;
1920       }
1921
1922     case AOP_CRY:
1923         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1924
1925       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1926       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1927       //if(PCOR(pcop)->r == NULL)
1928       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1929       return pcop;
1930         
1931     case AOP_LIT:
1932         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1933       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1934
1935     case AOP_STR:
1936       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1937       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1938
1939       /*
1940       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1941       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1942       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1943       pcop->type = PCOR(pcop)->r->pc_type;
1944       pcop->name = PCOR(pcop)->r->name;
1945
1946       return pcop;
1947       */
1948
1949     case AOP_PCODE:
1950       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1951                           __LINE__, 
1952                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1953       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1954 #if 1
1955         switch( aop->aopu.pcop->type ) {
1956                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1957                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1958                 default:
1959                         assert( 0 );    /* should never reach here */;
1960         }
1961 #else
1962       PCOI(pcop)->offset = offset;
1963 #endif
1964       return pcop;
1965     }
1966
1967     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1968            "pic16_popGet got unsupported aop->type");
1969     exit(0);
1970 }
1971 /*-----------------------------------------------------------------*/
1972 /* pic16_aopPut - puts a string for a aop                                */
1973 /*-----------------------------------------------------------------*/
1974 void pic16_aopPut (asmop *aop, char *s, int offset)
1975 {
1976     char *d = buffer ;
1977     symbol *lbl ;
1978
1979     return;
1980
1981     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1982
1983     if (aop->size && offset > ( aop->size - 1)) {
1984         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1985                "pic16_aopPut got offset > aop->size");
1986         exit(0);
1987     }
1988
1989     /* will assign value to value */
1990     /* depending on where it is ofcourse */
1991     switch (aop->type) {
1992     case AOP_DIR:
1993       if (offset) {
1994         sprintf(d,"(%s + %d)",
1995                 aop->aopu.aop_dir,offset);
1996         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1997
1998       } else
1999             sprintf(d,"%s",aop->aopu.aop_dir);
2000         
2001         if (strcmp(d,s)) {
2002           DEBUGpic16_emitcode(";","%d",__LINE__);
2003           if(strcmp(s,"W"))
2004             pic16_emitcode("movf","%s,w",s);
2005           pic16_emitcode("movwf","%s",d);
2006
2007           if(strcmp(s,"W")) {
2008             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2009             if(offset >= aop->size) {
2010               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2011               break;
2012             } else
2013               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2014           }
2015
2016           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2017
2018
2019         }
2020         break;
2021         
2022     case AOP_REG:
2023       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2024         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2025           /*
2026             if (*s == '@'           ||
2027                 strcmp(s,"r0") == 0 ||
2028                 strcmp(s,"r1") == 0 ||
2029                 strcmp(s,"r2") == 0 ||
2030                 strcmp(s,"r3") == 0 ||
2031                 strcmp(s,"r4") == 0 ||
2032                 strcmp(s,"r5") == 0 ||
2033                 strcmp(s,"r6") == 0 || 
2034                 strcmp(s,"r7") == 0 )
2035                 pic16_emitcode("mov","%s,%s  ; %d",
2036                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2037             else
2038           */
2039
2040           if(strcmp(s,"W")==0 )
2041             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2042
2043           pic16_emitcode("movwf","%s",
2044                    aop->aopu.aop_reg[offset]->name);
2045
2046           if(strcmp(s,zero)==0) {
2047             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2048
2049           } else if(strcmp(s,"W")==0) {
2050             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2051             pcop->type = PO_GPR_REGISTER;
2052
2053             PCOR(pcop)->rIdx = -1;
2054             PCOR(pcop)->r = NULL;
2055
2056             DEBUGpic16_emitcode(";","%d",__LINE__);
2057             pcop->name = Safe_strdup(s);
2058             pic16_emitpcode(POC_MOVFW,pcop);
2059             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2060           } else if(strcmp(s,one)==0) {
2061             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2062             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2063           } else {
2064             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2065           }
2066         }
2067         break;
2068         
2069     case AOP_DPTR:
2070     case AOP_DPTR2:
2071     
2072     if (aop->type == AOP_DPTR2)
2073     {
2074         genSetDPTR(1);
2075     }
2076     
2077         if (aop->code) {
2078             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2079                    "pic16_aopPut writting to code space");
2080             exit(0);
2081         }
2082         
2083         while (offset > aop->coff) {
2084             aop->coff++;
2085             pic16_emitcode ("inc","dptr");
2086         }
2087         
2088         while (offset < aop->coff) {
2089             aop->coff-- ;
2090             pic16_emitcode("lcall","__decdptr");
2091         }
2092         
2093         aop->coff = offset;
2094         
2095         /* if not in accumulater */
2096         MOVA(s);        
2097         
2098         pic16_emitcode ("movx","@dptr,a");
2099         
2100     if (aop->type == AOP_DPTR2)
2101     {
2102         genSetDPTR(0);
2103     }
2104         break;
2105         
2106     case AOP_R0:
2107     case AOP_R1:
2108         while (offset > aop->coff) {
2109             aop->coff++;
2110             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2111         }
2112         while (offset < aop->coff) {
2113             aop->coff-- ;
2114             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2115         }
2116         aop->coff = offset;
2117         
2118         if (aop->paged) {
2119             MOVA(s);           
2120             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2121             
2122         } else
2123             if (*s == '@') {
2124                 MOVA(s);
2125                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2126             } else
2127                 if (strcmp(s,"r0") == 0 ||
2128                     strcmp(s,"r1") == 0 ||
2129                     strcmp(s,"r2") == 0 ||
2130                     strcmp(s,"r3") == 0 ||
2131                     strcmp(s,"r4") == 0 ||
2132                     strcmp(s,"r5") == 0 ||
2133                     strcmp(s,"r6") == 0 || 
2134                     strcmp(s,"r7") == 0 ) {
2135                     char buffer[10];
2136                     sprintf(buffer,"a%s",s);
2137                     pic16_emitcode("mov","@%s,%s",
2138                              aop->aopu.aop_ptr->name,buffer);
2139                 } else
2140                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2141         
2142         break;
2143         
2144     case AOP_STK:
2145         if (strcmp(s,"a") == 0)
2146             pic16_emitcode("push","acc");
2147         else
2148             pic16_emitcode("push","%s",s);
2149         
2150         break;
2151         
2152     case AOP_CRY:
2153         /* if bit variable */
2154         if (!aop->aopu.aop_dir) {
2155             pic16_emitcode("clr","a");
2156             pic16_emitcode("rlc","a");
2157         } else {
2158             if (s == zero) 
2159                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2160             else
2161                 if (s == one)
2162                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2163                 else
2164                     if (!strcmp(s,"c"))
2165                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2166                     else {
2167                         lbl = newiTempLabel(NULL);
2168                         
2169                         if (strcmp(s,"a")) {
2170                             MOVA(s);
2171                         }
2172                         pic16_emitcode("clr","c");
2173                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2174                         pic16_emitcode("cpl","c");
2175                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2176                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2177                     }
2178         }
2179         break;
2180         
2181     case AOP_STR:
2182         aop->coff = offset;
2183         if (strcmp(aop->aopu.aop_str[offset],s))
2184             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2185         break;
2186         
2187     case AOP_ACC:
2188         aop->coff = offset;
2189         if (!offset && (strcmp(s,"acc") == 0))
2190             break;
2191         
2192         if (strcmp(aop->aopu.aop_str[offset],s))
2193             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2194         break;
2195
2196     default :
2197         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2198 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2199 //             "pic16_aopPut got unsupported aop->type");
2200 //      exit(0);    
2201     }    
2202
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2207 /*-----------------------------------------------------------------*/
2208 static void mov2w (asmop *aop, int offset)
2209 {
2210   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2211
2212   if(is_LitAOp(aop))
2213     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2214   else
2215     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2216 }
2217
2218 static void mov2f(asmop *dst, asmop *src, int offset)
2219 {
2220   if(is_LitAOp(src)) {
2221     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2222     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2223   } else {
2224     if(pic16_sameRegsOfs(src, dst, offset))return;
2225     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2226                       pic16_popGet(dst, offset)));
2227   }
2228 }
2229
2230 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2231 {
2232   if(is_LitAOp(src)) {
2233     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2234     pic16_emitpcode(POC_MOVWF, dst);
2235   } else {
2236     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2237   }
2238 }
2239
2240 void pic16_testStackOverflow(void)
2241 {
2242 #define GSTACK_TEST_NAME        "__gstack_test"
2243
2244   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2245   
2246   {
2247     symbol *sym;
2248
2249       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2250       strcpy(sym->rname, GSTACK_TEST_NAME);
2251       checkAddSym(&externs, sym);
2252   }
2253
2254 }
2255
2256 /* push pcop into stack */
2257 void pic16_pushpCodeOp(pCodeOp *pcop)
2258 {
2259 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2260   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2261   if(pic16_options.gstack)
2262     pic16_testStackOverflow();
2263     
2264 }
2265
2266 /* pop pcop from stack */
2267 void pic16_poppCodeOp(pCodeOp *pcop)
2268 {
2269   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2270   if(pic16_options.gstack)
2271     pic16_testStackOverflow();
2272 }
2273
2274
2275 /*-----------------------------------------------------------------*/
2276 /* pushw - pushes wreg to stack                                    */
2277 /*-----------------------------------------------------------------*/
2278 void pushw(void)
2279 {
2280   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2281   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2282   if(pic16_options.gstack)
2283     pic16_testStackOverflow();
2284 }
2285
2286                 
2287 /*-----------------------------------------------------------------*/
2288 /* pushaop - pushes aop to stack                                   */
2289 /*-----------------------------------------------------------------*/
2290 void pushaop(asmop *aop, int offset)
2291 {
2292   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2293
2294   if(is_LitAOp(aop)) {
2295     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2296     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2297   } else {
2298     pic16_emitpcode(POC_MOVFF,
2299       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2300   }
2301
2302 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2303   if(pic16_options.gstack)
2304     pic16_testStackOverflow();
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* popaop - pops aop from stack                                    */
2309 /*-----------------------------------------------------------------*/
2310 void popaop(asmop *aop, int offset)
2311 {
2312   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2313   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2314   if(pic16_options.gstack)
2315     pic16_testStackOverflow();
2316 }
2317
2318 void popaopidx(asmop *aop, int offset, int index)
2319 {
2320   int ofs=1;
2321
2322     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2323
2324     if(STACK_MODEL_LARGE)ofs++;
2325
2326     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2327     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2328     if(pic16_options.gstack)
2329       pic16_testStackOverflow();
2330 }
2331
2332 /*-----------------------------------------------------------------*/
2333 /* reAdjustPreg - points a register back to where it should        */
2334 /*-----------------------------------------------------------------*/
2335 static void reAdjustPreg (asmop *aop)
2336 {
2337     int size ;
2338
2339     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2340     aop->coff = 0;
2341     if ((size = aop->size) <= 1)
2342         return ;
2343     size-- ;
2344     switch (aop->type) {
2345         case AOP_R0 :
2346         case AOP_R1 :
2347             while (size--)
2348                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2349             break;          
2350         case AOP_DPTR :
2351         case AOP_DPTR2:
2352             if (aop->type == AOP_DPTR2)
2353             {
2354                 genSetDPTR(1);
2355             } 
2356             while (size--)
2357             {
2358                 pic16_emitcode("lcall","__decdptr");
2359             }
2360                 
2361             if (aop->type == AOP_DPTR2)
2362             {
2363                 genSetDPTR(0);
2364             }                
2365             break;  
2366
2367     }   
2368
2369 }
2370
2371
2372 #if 0
2373 /*-----------------------------------------------------------------*/
2374 /* opIsGptr: returns non-zero if the passed operand is             */   
2375 /* a generic pointer type.                                         */
2376 /*-----------------------------------------------------------------*/ 
2377 static int opIsGptr(operand *op)
2378 {
2379     sym_link *type = operandType(op);
2380     
2381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2382     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2383     {
2384         return 1;
2385     }
2386     return 0;        
2387 }
2388 #endif
2389
2390 /*-----------------------------------------------------------------*/
2391 /* pic16_getDataSize - get the operand data size                         */
2392 /*-----------------------------------------------------------------*/
2393 int pic16_getDataSize(operand *op)
2394 {
2395     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2396
2397
2398     return AOP_SIZE(op);
2399
2400     // tsd- in the pic port, the genptr size is 1, so this code here
2401     // fails. ( in the 8051 port, the size was 4).
2402 #if 0
2403     int size;
2404     size = AOP_SIZE(op);
2405     if (size == GPTRSIZE)
2406     {
2407         sym_link *type = operandType(op);
2408         if (IS_GENPTR(type))
2409         {
2410             /* generic pointer; arithmetic operations
2411              * should ignore the high byte (pointer type).
2412              */
2413             size--;
2414     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2415         }
2416     }
2417     return size;
2418 #endif
2419 }
2420
2421 /*-----------------------------------------------------------------*/
2422 /* pic16_outAcc - output Acc                                             */
2423 /*-----------------------------------------------------------------*/
2424 void pic16_outAcc(operand *result)
2425 {
2426   int size,offset;
2427   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2428   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2429
2430
2431   size = pic16_getDataSize(result);
2432   if(size){
2433     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2434     size--;
2435     offset = 1;
2436     /* unsigned or positive */
2437     while(size--)
2438       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2439   }
2440
2441 }
2442
2443 /*-----------------------------------------------------------------*/
2444 /* pic16_outBitC - output a bit C                                  */
2445 /*                 Move to result the value of Carry flag -- VR    */
2446 /*-----------------------------------------------------------------*/
2447 void pic16_outBitC(operand *result)
2448 {
2449   int i;
2450
2451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2452     /* if the result is bit */
2453     if (AOP_TYPE(result) == AOP_CRY) {
2454         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2455         pic16_aopPut(AOP(result),"c",0);
2456     } else {
2457
2458         i = AOP_SIZE(result);
2459         while(i--) {
2460                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2461         }
2462         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2463         
2464 /*
2465         pic16_emitcode("clr","a  ; %d", __LINE__);
2466         pic16_emitcode("rlc","a");
2467         pic16_outAcc(result);
2468 */
2469     }
2470 }
2471
2472 /*-----------------------------------------------------------------*/
2473 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2474 /*-----------------------------------------------------------------*/
2475 void pic16_toBoolean(operand *oper)
2476 {
2477     int size = AOP_SIZE(oper) - 1;
2478     int offset = 1;
2479
2480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2481
2482     if ( AOP_TYPE(oper) != AOP_ACC) {
2483       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2484     }
2485     while (size--) {
2486       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2487     }
2488 }
2489
2490
2491 #if !defined(GEN_Not)
2492 /*-----------------------------------------------------------------*/
2493 /* genNot - generate code for ! operation                          */
2494 /*-----------------------------------------------------------------*/
2495 static void pic16_genNot (iCode *ic)
2496 {
2497   symbol *tlbl;
2498   int size;
2499
2500   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2501   /* assign asmOps to operand & result */
2502   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2503   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2504
2505   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2506   /* if in bit space then a special case */
2507   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2508     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2509       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2510       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2511     } else {
2512       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2513       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2514       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2515     }
2516     goto release;
2517   }
2518
2519   size = AOP_SIZE(IC_LEFT(ic));
2520   if(size == 1) {
2521     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2522     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2523     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2524     goto release;
2525   }
2526   pic16_toBoolean(IC_LEFT(ic));
2527
2528   tlbl = newiTempLabel(NULL);
2529   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2530   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2531   pic16_outBitC(IC_RESULT(ic));
2532
2533  release:    
2534   /* release the aops */
2535   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2536   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2537 }
2538 #endif
2539
2540
2541 #if !defined(GEN_Cpl)
2542 /*-----------------------------------------------------------------*/
2543 /* genCpl - generate code for complement                           */
2544 /*-----------------------------------------------------------------*/
2545 static void pic16_genCpl (iCode *ic)
2546 {
2547     int offset = 0;
2548     int size ;
2549
2550
2551     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2552     /* assign asmOps to operand & result */
2553     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2554     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2555
2556     /* if both are in bit space then 
2557     a special case */
2558     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2559         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2560
2561         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2562         pic16_emitcode("cpl","c"); 
2563         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2564         goto release; 
2565     } 
2566
2567     size = AOP_SIZE(IC_RESULT(ic));
2568     while (size--) {
2569 /*
2570         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2571         MOVA(l);       
2572         pic16_emitcode("cpl","a");
2573         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2574 */
2575         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2576               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2577         } else {
2578                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2579                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2580         }
2581         offset++;
2582
2583     }
2584
2585
2586 release:
2587     /* release the aops */
2588     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2589     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2590 }
2591 #endif
2592
2593 /*-----------------------------------------------------------------*/
2594 /* genUminusFloat - unary minus for floating points                */
2595 /*-----------------------------------------------------------------*/
2596 static void genUminusFloat(operand *op,operand *result)
2597 {
2598     int size ,offset =0 ;
2599     char *l;
2600
2601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2602     /* for this we just need to flip the 
2603     first it then copy the rest in place */
2604     size = AOP_SIZE(op) - 1;
2605     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2606
2607     MOVA(l);    
2608
2609     pic16_emitcode("cpl","acc.7");
2610     pic16_aopPut(AOP(result),"a",3);    
2611
2612     while(size--) {
2613         pic16_aopPut(AOP(result),
2614                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2615                offset);
2616         offset++;
2617     }          
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* genUminus - unary minus code generation                         */
2622 /*-----------------------------------------------------------------*/
2623 static void genUminus (iCode *ic)
2624 {
2625   int size, i;
2626   sym_link *optype, *rtype;
2627
2628         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2629         
2630         /* assign asmops */
2631         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2632         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2633
2634         /* if both in bit space then special case */
2635         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2636                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2637
2638                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2639                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2640                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2641                 
2642                 goto release; 
2643         } 
2644
2645         optype = operandType(IC_LEFT(ic));
2646         rtype = operandType(IC_RESULT(ic));
2647
2648         /* if float then do float stuff */
2649         if (IS_FLOAT(optype)) {
2650                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2651                 goto release;
2652         }
2653
2654         /* otherwise subtract from zero by taking the 2's complement */
2655         size = AOP_SIZE(IC_LEFT(ic));
2656
2657         for(i=0; i<size; i++) {
2658                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2659                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2660                 else {
2661                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2662                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2663                 }
2664         }
2665
2666         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2667         for(i=1; i<size; i++) {
2668                 emitSKPNZ;
2669                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2670         }
2671
2672 release:
2673         /* release the aops */
2674         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2675         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2676 }
2677
2678 #if 0
2679 /*-----------------------------------------------------------------*/
2680 /* saveRegisters - will look for a call and save the registers     */
2681 /*-----------------------------------------------------------------*/
2682 static void saveRegisters(iCode *lic) 
2683 {
2684     int i;
2685     iCode *ic;
2686     bitVect *rsave;
2687     sym_link *dtype;
2688
2689     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2690     /* look for call */
2691     for (ic = lic ; ic ; ic = ic->next) 
2692         if (ic->op == CALL || ic->op == PCALL)
2693             break;
2694
2695     if (!ic) {
2696         fprintf(stderr,"found parameter push with no function call\n");
2697         return ;
2698     }
2699
2700     /* if the registers have been saved already then
2701     do nothing */
2702     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2703         return ;
2704
2705     /* find the registers in use at this time 
2706     and push them away to safety */
2707     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2708                           ic->rUsed);
2709
2710     ic->regsSaved = 1;
2711     if (options.useXstack) {
2712         if (bitVectBitValue(rsave,R0_IDX))
2713             pic16_emitcode("mov","b,r0");
2714         pic16_emitcode("mov","r0,%s",spname);
2715         for (i = 0 ; i < pic16_nRegs ; i++) {
2716             if (bitVectBitValue(rsave,i)) {
2717                 if (i == R0_IDX)
2718                     pic16_emitcode("mov","a,b");
2719                 else
2720                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2721                 pic16_emitcode("movx","@r0,a");
2722                 pic16_emitcode("inc","r0");
2723             }
2724         }
2725         pic16_emitcode("mov","%s,r0",spname);
2726         if (bitVectBitValue(rsave,R0_IDX))
2727             pic16_emitcode("mov","r0,b");           
2728     }// else
2729     //for (i = 0 ; i < pic16_nRegs ; i++) {
2730     //    if (bitVectBitValue(rsave,i))
2731     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2732     //}
2733
2734     dtype = operandType(IC_LEFT(ic));
2735     if (currFunc && dtype && 
2736         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2737         IFFUNC_ISISR(currFunc->type) &&
2738         !ic->bankSaved) 
2739
2740         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2741
2742 }
2743 /*-----------------------------------------------------------------*/
2744 /* unsaveRegisters - pop the pushed registers                      */
2745 /*-----------------------------------------------------------------*/
2746 static void unsaveRegisters (iCode *ic)
2747 {
2748     int i;
2749     bitVect *rsave;
2750
2751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752     /* find the registers in use at this time 
2753     and push them away to safety */
2754     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2755                           ic->rUsed);
2756     
2757     if (options.useXstack) {
2758         pic16_emitcode("mov","r0,%s",spname);   
2759         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2760             if (bitVectBitValue(rsave,i)) {
2761                 pic16_emitcode("dec","r0");
2762                 pic16_emitcode("movx","a,@r0");
2763                 if (i == R0_IDX)
2764                     pic16_emitcode("mov","b,a");
2765                 else
2766                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2767             }       
2768
2769         }
2770         pic16_emitcode("mov","%s,r0",spname);
2771         if (bitVectBitValue(rsave,R0_IDX))
2772             pic16_emitcode("mov","r0,b");
2773     } //else
2774     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2775     //    if (bitVectBitValue(rsave,i))
2776     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2777     //}
2778
2779 }  
2780 #endif
2781
2782 #if 0  // patch 14
2783 /*-----------------------------------------------------------------*/
2784 /* pushSide -                                                      */
2785 /*-----------------------------------------------------------------*/
2786 static void pushSide(operand * oper, int size)
2787 {
2788         int offset = 0;
2789     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2790         while (size--) {
2791                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2792                 if (AOP_TYPE(oper) != AOP_REG &&
2793                     AOP_TYPE(oper) != AOP_DIR &&
2794                     strcmp(l,"a") ) {
2795                         pic16_emitcode("mov","a,%s",l);
2796                         pic16_emitcode("push","acc");
2797                 } else
2798                         pic16_emitcode("push","%s",l);
2799         }
2800 }
2801 #endif // patch 14
2802
2803 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2804 {
2805   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2806     pic16_emitpcode(POC_MOVFW, src);
2807     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2808   } else {
2809     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2810         src, pic16_popGet(AOP(op), offset)));
2811   }
2812 }
2813
2814
2815 /*-----------------------------------------------------------------*/
2816 /* assignResultValue - assign results to oper, rescall==1 is       */
2817 /*                     called from genCall() or genPcall()         */
2818 /*-----------------------------------------------------------------*/
2819 static void assignResultValue(operand * oper, int rescall)
2820 {
2821   int size = AOP_SIZE(oper);
2822   int offset=0;
2823   
2824     DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2825     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2826
2827     if(rescall) {
2828       /* assign result from a call/pcall function() */
2829                 
2830       /* function results are stored in a special order,
2831        * see top of file with Function return policy, or manual */
2832
2833       if(size <= 4) {
2834         /* 8-bits, result in WREG */
2835         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2836                         
2837         if(size>1) {
2838           /* 16-bits, result in PRODL:WREG */
2839           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2840         }
2841                         
2842         if(size>2) {
2843           /* 24-bits, result in PRODH:PRODL:WREG */
2844           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2845         }
2846                         
2847         if(size>3) {
2848           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2849           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2850         }
2851       
2852       } else {
2853         /* >32-bits, result on stack, and FSR0 points to beginning.
2854          * Fix stack when done */
2855         /* FIXME FIXME */
2856 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2857         while (size--) {
2858 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2859 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2860                 
2861           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2862           GpsuedoStkPtr++;
2863         }
2864                         
2865         /* fix stack */
2866         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2867         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2868         if(STACK_MODEL_LARGE) {
2869           emitSKPNC;
2870           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2871         }
2872       }                 
2873     } else {
2874       int areg = 0;             /* matching argument register */
2875       
2876 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2877       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2878
2879
2880       /* its called from genReceive (probably) -- VR */
2881       if(!GpsuedoStkPtr && _G.useWreg) {
2882 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2883
2884         /* The last byte in the assignment is in W */
2885         if(areg <= GpsuedoStkPtr) {
2886           size--;
2887           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2888           offset++;
2889 //          debugf("receive from WREG\n", 0);
2890         }
2891       }
2892 //      GpsuedoStkPtr++;
2893       _G.stack_lat = AOP_SIZE(oper)-1;
2894
2895       while (size) {
2896         size--;
2897         GpsuedoStkPtr++;
2898         popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2899 //        debugf("receive from STACK\n", 0);
2900         offset++;
2901       }
2902     }
2903 }
2904
2905
2906 /*-----------------------------------------------------------------*/
2907 /* genIpush - generate code for pushing this gets a little complex */
2908 /*-----------------------------------------------------------------*/
2909 static void genIpush (iCode *ic)
2910 {
2911 //  int size, offset=0;
2912
2913   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2914
2915   if(ic->parmPush) {
2916     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2917
2918     /* send to stack as normal */
2919     addSet(&_G.sendSet,ic);
2920 //    addSetHead(&_G.sendSet,ic);
2921     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2922   }
2923
2924         
2925 #if 0
2926     int size, offset = 0 ;
2927     char *l;
2928
2929
2930     /* if this is not a parm push : ie. it is spill push 
2931     and spill push is always done on the local stack */
2932     if (!ic->parmPush) {
2933
2934         /* and the item is spilt then do nothing */
2935         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2936             return ;
2937
2938         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2939         size = AOP_SIZE(IC_LEFT(ic));
2940         /* push it on the stack */
2941         while(size--) {
2942             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2943             if (*l == '#') {
2944                 MOVA(l);
2945                 l = "acc";
2946             }
2947             pic16_emitcode("push","%s",l);
2948         }
2949         return ;        
2950     }
2951
2952     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2953 #endif
2954 }
2955
2956 /*-----------------------------------------------------------------*/
2957 /* genIpop - recover the registers: can happen only for spilling   */
2958 /*-----------------------------------------------------------------*/
2959 static void genIpop (iCode *ic)
2960 {
2961   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2962 #if 0
2963     int size,offset ;
2964
2965
2966     /* if the temp was not pushed then */
2967     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2968         return ;
2969
2970     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2971     size = AOP_SIZE(IC_LEFT(ic));
2972     offset = (size-1);
2973     while (size--) 
2974         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2975                                    FALSE,TRUE));
2976
2977     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2978 #endif
2979 }
2980
2981 #if 0
2982 /*-----------------------------------------------------------------*/
2983 /* unsaverbank - restores the resgister bank from stack            */
2984 /*-----------------------------------------------------------------*/
2985 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2986 {
2987   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2988 #if 0
2989     int i;
2990     asmop *aop ;
2991     regs *r = NULL;
2992
2993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2994     if (popPsw) {
2995         if (options.useXstack) {
2996             aop = newAsmop(0);
2997             r = getFreePtr(ic,&aop,FALSE);
2998             
2999             
3000             pic16_emitcode("mov","%s,_spx",r->name);
3001             pic16_emitcode("movx","a,@%s",r->name);
3002             pic16_emitcode("mov","psw,a");
3003             pic16_emitcode("dec","%s",r->name);
3004             
3005         }else
3006             pic16_emitcode ("pop","psw");
3007     }
3008
3009     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3010         if (options.useXstack) {       
3011             pic16_emitcode("movx","a,@%s",r->name);
3012             //pic16_emitcode("mov","(%s+%d),a",
3013             //       regspic16[i].base,8*bank+regspic16[i].offset);
3014             pic16_emitcode("dec","%s",r->name);
3015
3016         } else 
3017           pic16_emitcode("pop",""); //"(%s+%d)",
3018         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3019     }
3020
3021     if (options.useXstack) {
3022
3023         pic16_emitcode("mov","_spx,%s",r->name);
3024         pic16_freeAsmop(NULL,aop,ic,TRUE);
3025
3026     }
3027 #endif 
3028 }
3029
3030 /*-----------------------------------------------------------------*/
3031 /* saverbank - saves an entire register bank on the stack          */
3032 /*-----------------------------------------------------------------*/
3033 static void saverbank (int bank, iCode *ic, bool pushPsw)
3034 {
3035   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3036 #if 0
3037     int i;
3038     asmop *aop ;
3039     regs *r = NULL;
3040
3041     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3042     if (options.useXstack) {
3043
3044         aop = newAsmop(0);
3045         r = getFreePtr(ic,&aop,FALSE);  
3046         pic16_emitcode("mov","%s,_spx",r->name);
3047
3048     }
3049
3050     for (i = 0 ; i < pic16_nRegs ;i++) {
3051         if (options.useXstack) {
3052             pic16_emitcode("inc","%s",r->name);
3053             //pic16_emitcode("mov","a,(%s+%d)",
3054             //         regspic16[i].base,8*bank+regspic16[i].offset);
3055             pic16_emitcode("movx","@%s,a",r->name);           
3056         } else 
3057           pic16_emitcode("push","");// "(%s+%d)",
3058                      //regspic16[i].base,8*bank+regspic16[i].offset);
3059     }
3060     
3061     if (pushPsw) {
3062         if (options.useXstack) {
3063             pic16_emitcode("mov","a,psw");
3064             pic16_emitcode("movx","@%s,a",r->name);     
3065             pic16_emitcode("inc","%s",r->name);
3066             pic16_emitcode("mov","_spx,%s",r->name);       
3067             pic16_freeAsmop (NULL,aop,ic,TRUE);
3068             
3069         } else
3070             pic16_emitcode("push","psw");
3071         
3072         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3073     }
3074     ic->bankSaved = 1;
3075 #endif
3076 }
3077 #endif  /* 0 */
3078
3079
3080 static int wparamCmp(void *p1, void *p2)
3081 {
3082   return (!strcmp((char *)p1, (char *)p2));
3083 }
3084
3085 int inWparamList(char *s)
3086 {
3087   return isinSetWith(wparamList, s, wparamCmp);
3088
3089
3090
3091 /*-----------------------------------------------------------------*/
3092 /* genCall - generates a call statement                            */
3093 /*-----------------------------------------------------------------*/
3094 static void genCall (iCode *ic)
3095 {
3096   sym_link *ftype;   
3097   int stackParms=0;
3098   int use_wreg=0;
3099   int inwparam=0;
3100   char *fname;
3101   
3102     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3103
3104     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3105     /* if caller saves & we have not saved then */
3106 //    if (!ic->regsSaved)
3107 //      saveRegisters(ic);
3108
3109         /* initialise stackParms for IPUSH pushes */
3110 //      stackParms = psuedoStkPtr;
3111 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3112     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3113     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3114
3115 #if 0
3116     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3117 #endif
3118
3119     /* if send set is not empty the assign */
3120     if (_G.sendSet) {
3121       iCode *sic;
3122       int psuedoStkPtr=-1; 
3123       int firstTimeThruLoop = 1;
3124
3125
3126         /* reverse sendSet if function is not reentrant */
3127         if(!IFFUNC_ISREENT(ftype))
3128           _G.sendSet = reverseSet(_G.sendSet);
3129
3130         /* First figure how many parameters are getting passed */
3131         stackParms = 0;
3132         use_wreg = 0;
3133         
3134         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3135           int size;
3136 //          int offset = 0;
3137
3138             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3139             size = AOP_SIZE(IC_LEFT(sic));
3140
3141             stackParms += size;
3142
3143             /* pass the last byte through WREG */
3144             if(inwparam) {
3145
3146               while (size--) {
3147                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3148                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3149                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3150
3151                 if(!firstTimeThruLoop) {
3152                   /* If this is not the first time we've been through the loop
3153                    * then we need to save the parameter in a temporary
3154                    * register. The last byte of the last parameter is
3155                    * passed in W. */
3156
3157                   pushw();
3158 //                  --psuedoStkPtr;             // sanity check
3159                   use_wreg = 1;
3160                 }
3161                 
3162                 firstTimeThruLoop=0;
3163
3164                 mov2w (AOP(IC_LEFT(sic)), size);
3165
3166 //                offset++;
3167               }
3168             } else {
3169               /* all arguments are passed via stack */
3170               use_wreg = 0;
3171
3172               while (size--) {
3173                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3174                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3175                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3176
3177 //                pushaop(AOP(IC_LEFT(sic)), size);
3178                 mov2w (AOP(IC_LEFT(sic)), size);
3179                 pushw();
3180               }
3181             }
3182
3183             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3184           }
3185
3186           if(inwparam) {
3187             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3188               pushw();  /* save last parameter to stack if functions has varargs */
3189               use_wreg = 0;
3190             } else
3191               use_wreg = 1;
3192           } else use_wreg = 0;
3193
3194           _G.stackRegSet = _G.sendSet;
3195           _G.sendSet = NULL;
3196     }
3197
3198     /* make the call */
3199     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3200
3201     GpsuedoStkPtr=0;
3202     
3203     /* if we need to assign a result value */
3204     if ((IS_ITEMP(IC_RESULT(ic))
3205           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3206               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3207         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3208
3209       _G.accInUse++;
3210       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3211       _G.accInUse--;
3212
3213       assignResultValue(IC_RESULT(ic), 1);
3214
3215       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3216                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3217                 
3218       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3219     }
3220
3221     if(!stackParms && ic->parmBytes) {
3222       stackParms = ic->parmBytes;
3223     }
3224       
3225     stackParms -= use_wreg;
3226     
3227     if(stackParms>0) {
3228       if(stackParms == 1) {
3229         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3230       } else {
3231         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3232         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3233       }
3234       if(STACK_MODEL_LARGE) {
3235         emitSKPNC;
3236         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3237       }
3238     }
3239
3240 #if 0
3241     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3242 #endif
3243
3244     /* adjust the stack for parameters if required */
3245 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3246
3247 #if 0
3248       /* if register bank was saved then pop them */
3249       if (ic->bankSaved)
3250         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3251
3252       /* if we hade saved some registers then unsave them */
3253       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3254         unsaveRegisters (ic);
3255 #endif
3256 }
3257
3258
3259
3260 /*-----------------------------------------------------------------*/
3261 /* genPcall - generates a call by pointer statement                */
3262 /*            new version, created from genCall - HJD              */
3263 /*-----------------------------------------------------------------*/
3264 static void genPcall (iCode *ic)
3265 {
3266   sym_link *ftype, *fntype;
3267   int stackParms=0;
3268   symbol *retlbl = newiTempLabel(NULL);
3269   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3270   
3271     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3272
3273     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3274     fntype = operandType( IC_LEFT(ic) )->next;
3275
3276     /* if send set is not empty the assign */
3277     if (_G.sendSet) {
3278       iCode *sic;
3279       int psuedoStkPtr=-1; 
3280
3281       /* reverse sendSet if function is not reentrant */
3282       if(!IFFUNC_ISREENT(fntype))
3283         _G.sendSet = reverseSet(_G.sendSet);
3284
3285       stackParms = 0;
3286       
3287       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3288         int size;
3289
3290           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3291           size = AOP_SIZE(IC_LEFT(sic));
3292           stackParms += size;
3293
3294           /* all parameters are passed via stack, since WREG is clobbered
3295            * by the calling sequence */
3296           while (size--) {
3297             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3298             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3299             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3300
3301             mov2w (AOP(IC_LEFT(sic)), size);
3302             pushw();
3303           }
3304
3305           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3306       }
3307
3308       _G.stackRegSet = _G.sendSet;
3309       _G.sendSet = NULL;
3310     }
3311
3312     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3313
3314     // push return address
3315     // push $ on return stack, then replace with retlbl
3316
3317     pic16_emitpcodeNULLop(POC_PUSH);
3318
3319     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3320     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3321     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3322     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3323     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3324     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3325
3326     /* make the call by writing the pointer into pc */
3327     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3328     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3329
3330     // note: MOVFF to PCL not allowed
3331     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3332     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3333
3334
3335     /* return address is here: (X) */
3336     pic16_emitpLabelFORCE(retlbl->key);
3337
3338     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3339
3340     GpsuedoStkPtr=0;
3341     /* if we need assign a result value */
3342     if ((IS_ITEMP(IC_RESULT(ic))
3343           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3344               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3345         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3346
3347       _G.accInUse++;
3348       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3349       _G.accInUse--;
3350
3351       assignResultValue(IC_RESULT(ic), 1);
3352
3353       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3354               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3355                 
3356       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3357     }
3358
3359 //    stackParms -= use_wreg;
3360     
3361     if(stackParms>0) {
3362       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3363       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3364       if(STACK_MODEL_LARGE) {
3365         /* this implies that stackParms < 256 !!! -- VR */
3366         emitSKPNC;
3367         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3368       }
3369     }
3370 }
3371
3372 /*-----------------------------------------------------------------*/
3373 /* resultRemat - result  is rematerializable                       */
3374 /*-----------------------------------------------------------------*/
3375 static int resultRemat (iCode *ic)
3376 {
3377   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3378   if (SKIP_IC(ic) || ic->op == IFX)
3379     return 0;
3380
3381   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3382     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3383     if (sym->remat && !POINTER_SET(ic)) 
3384       return 1;
3385   }
3386
3387   return 0;
3388 }
3389
3390 #if defined(__BORLANDC__) || defined(_MSC_VER)
3391 #define STRCASECMP stricmp
3392 #else
3393 #define STRCASECMP strcasecmp
3394 #endif
3395
3396 #if 0
3397 /*-----------------------------------------------------------------*/
3398 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3399 /*-----------------------------------------------------------------*/
3400 static bool inExcludeList(char *s)
3401 {
3402   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3403     int i =0;
3404     
3405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3406     if (options.excludeRegs[i] &&
3407     STRCASECMP(options.excludeRegs[i],"none") == 0)
3408         return FALSE ;
3409
3410     for ( i = 0 ; options.excludeRegs[i]; i++) {
3411         if (options.excludeRegs[i] &&
3412         STRCASECMP(s,options.excludeRegs[i]) == 0)
3413             return TRUE;
3414     }
3415     return FALSE ;
3416 }
3417 #endif
3418
3419 /*-----------------------------------------------------------------*/
3420 /* genFunction - generated code for function entry                 */
3421 /*-----------------------------------------------------------------*/
3422 static void genFunction (iCode *ic)
3423 {
3424   symbol *sym;
3425   sym_link *ftype;
3426   
3427     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3428
3429     pic16_labelOffset += (max_key+4);
3430     max_key=0;
3431     GpsuedoStkPtr=0;
3432     _G.nRegsSaved = 0;
3433         
3434     ftype = operandType(IC_LEFT(ic));
3435     sym = OP_SYMBOL(IC_LEFT(ic));
3436
3437     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3438       /* create an absolute section at the interrupt vector:
3439        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3440       symbol *asym;
3441       char asymname[128];
3442       pBlock *apb;
3443
3444         {
3445           int i, found=-1;
3446
3447             sym = OP_SYMBOL( IC_LEFT(ic));
3448             for(i=0;i<=2;i++) {
3449               if(interrupts[i]->name
3450                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3451                   found = i;
3452                   break;
3453               }
3454             }
3455                         
3456             if(found == -1) {
3457               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3458                             __FILE__, __LINE__, sym->name);
3459               assert( 0 );
3460             }
3461             _G.interruptvector = found;
3462         }
3463
3464         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3465         asym = newSymbol(asymname, 0);
3466
3467         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3468         pic16_addpBlock( apb );
3469
3470         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3471         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3472         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3473                 
3474         /* mark the end of this tiny function */
3475         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3476
3477         {
3478           absSym *abSym;
3479
3480             abSym = Safe_calloc(1, sizeof(absSym));
3481             strcpy(abSym->name, asymname);
3482
3483             switch( _G.interruptvector ) {
3484               case 0: abSym->address = 0x000000; break;
3485               case 1: abSym->address = 0x000008; break;
3486               case 2: abSym->address = 0x000018; break;
3487             }
3488
3489             /* relocate interrupt vectors if needed */
3490             abSym->address += pic16_options.ivt_loc;
3491
3492             addSet(&absSymSet, abSym);
3493         }
3494     }
3495
3496     /* create the function header */
3497     pic16_emitcode(";","-----------------------------------------");
3498     pic16_emitcode(";"," function %s",sym->name);
3499     pic16_emitcode(";","-----------------------------------------");
3500
3501     pic16_emitcode("","%s:",sym->rname);
3502     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3503
3504
3505     {
3506       absSym *ab;
3507
3508         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3509           if(!strcmp(ab->name, sym->rname)) {
3510             pic16_pBlockConvert2Absolute(pb);
3511             break;
3512           }
3513         }
3514     }
3515
3516
3517     if(IFFUNC_ISNAKED(ftype)) {
3518       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3519       return;
3520     }
3521         
3522     /* if critical function then turn interrupts off */
3523     if (IFFUNC_ISCRITICAL(ftype)) {
3524       //pic16_emitcode("clr","ea");
3525     }
3526
3527     _G.fregsUsed = sym->regsUsed;
3528
3529     /* if this is an interrupt service routine then
3530      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3531     if (IFFUNC_ISISR(sym->type)) {
3532         _G.usefastretfie = 1;   /* use shadow registers by default */
3533         
3534         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3535         if(!(_G.interruptvector == 1)) {
3536           /* do not save WREG,STATUS,BSR for high priority interrupts
3537            * because they are stored in the hardware shadow registers already */
3538           _G.usefastretfie = 0;
3539           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3540           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3541           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3542         }
3543
3544         /* these should really be optimized somehow, because not all
3545          * interrupt handlers modify them */
3546         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3547         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3548         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3549         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3550         
3551 //        pic16_pBlockConvert2ISR(pb);
3552                 
3553     }
3554
3555     /* emit code to setup stack frame if user enabled,
3556      * and function is not main() */
3557          
3558     //fprintf(stderr, "function name: %s\n", sym->name);
3559     if(strcmp(sym->name, "main")) {
3560       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3561         /* setup the stack frame */
3562         if(STACK_MODEL_LARGE)
3563           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3564         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3565 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3566         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3567         if(STACK_MODEL_LARGE)
3568           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3569       }
3570     }
3571
3572     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3573           && sym->stack) {
3574
3575       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3576
3577       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3578       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3579       emitSKPNC;
3580       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3581     }
3582           
3583     if(inWparamList(sym->name)) {
3584       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3585         _G.useWreg = 0;
3586       else
3587         _G.useWreg = 1;
3588     } else
3589       _G.useWreg = 0;
3590
3591     /* if callee-save to be used for this function
3592      * then save the registers being used in this function */
3593 //    if (IFFUNC_CALLEESAVES(sym->type))
3594     {
3595       int i;
3596
3597         /* if any registers used */
3598         if (sym->regsUsed) {
3599           /* save the registers used */
3600           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3601           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3602           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3603             if (bitVectBitValue(sym->regsUsed,i)) {
3604               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3605               _G.nRegsSaved++;
3606
3607               if(!pic16_regWithIdx(i)->wasUsed) {
3608                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3609                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3610                 pic16_regWithIdx(i)->wasUsed = 1;
3611               }
3612             }
3613           }
3614           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3615         }
3616     }
3617         
3618     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3619 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3620 }
3621
3622 /*-----------------------------------------------------------------*/
3623 /* genEndFunction - generates epilogue for functions               */
3624 /*-----------------------------------------------------------------*/
3625 static void genEndFunction (iCode *ic)
3626 {
3627   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3628
3629     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3630
3631     if(IFFUNC_ISNAKED(sym->type)) {
3632       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3633       return;
3634     }
3635
3636     _G.stack_lat = 0;
3637
3638     /* add code for ISCRITICAL */
3639     if(IFFUNC_ISCRITICAL(sym->type)) {
3640       /* if critical function, turn on interrupts */
3641       
3642       /* TODO: add code here -- VR */
3643     }
3644     
3645     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3646           && sym->stack) {
3647       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3648       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3649       emitSKPNC;
3650       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3651     }
3652
3653     /* now we need to restore the registers */
3654     /* if any registers used */
3655     if (sym->regsUsed) {
3656       int i;
3657
3658         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3659         /* restore registers used */
3660         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3661         for ( i = sym->regsUsed->size; i >= 0; i--) {
3662           if (bitVectBitValue(sym->regsUsed,i)) {
3663             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3664             _G.nRegsSaved--;
3665           }
3666         }
3667         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3668
3669     }
3670
3671     if(strcmp(sym->name, "main")) {
3672       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3673         /* restore stack frame */
3674         if(STACK_MODEL_LARGE)
3675           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3676 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3677         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3678 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3679       }
3680     }
3681
3682     _G.useWreg = 0;
3683
3684     if (IFFUNC_ISISR(sym->type)) {
3685       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3686       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3687       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3688       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3689
3690       if(!(_G.interruptvector == 1)) {
3691         /* do not restore interrupt vector for WREG,STATUS,BSR
3692          * for high priority interrupt, see genFunction */
3693         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3694         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3695         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3696       }
3697       _G.interruptvector = 0;           /* sanity check */
3698
3699
3700       /* if debug then send end of function */
3701 /*      if (options.debug && currFunc)  */
3702       if (currFunc) {
3703         debugFile->writeEndFunction (currFunc, ic, 1);
3704       }
3705         
3706       if(_G.usefastretfie)
3707         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3708       else
3709         pic16_emitpcodeNULLop(POC_RETFIE);
3710
3711       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3712       
3713       _G.usefastretfie = 0;
3714       return;
3715     }
3716
3717     if (IFFUNC_ISCRITICAL(sym->type)) {
3718       pic16_emitcode("setb","ea");
3719     }
3720
3721     /* if debug then send end of function */
3722     if (currFunc) {
3723       debugFile->writeEndFunction (currFunc, ic, 1);
3724     }
3725
3726     /* insert code to restore stack frame, if user enabled it
3727      * and function is not main() */
3728          
3729
3730     pic16_emitpcodeNULLop(POC_RETURN);
3731
3732     /* Mark the end of a function */
3733     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3734 }
3735
3736
3737 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3738 {
3739   if(is_LitOp(op)) {
3740     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3741     if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3742   } else {
3743     if(dest->type == PO_WREG && (offset == 0)) {
3744       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3745       return;
3746     }
3747     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3748   }
3749 }
3750
3751 /*-----------------------------------------------------------------*/
3752 /* genRet - generate code for return statement                     */
3753 /*-----------------------------------------------------------------*/
3754 static void genRet (iCode *ic)
3755 {
3756   int size;
3757   operand *left;
3758
3759         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3760         /* if we have no return value then
3761          * just generate the "ret" */
3762         
3763         if (!IC_LEFT(ic)) 
3764                 goto jumpret;       
3765     
3766         /* we have something to return then
3767          * move the return value into place */
3768         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3769         size = AOP_SIZE(IC_LEFT(ic));
3770
3771         if(size <= 4) {
3772                 if(size>3) {
3773                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3774 //                      pic16_emitpcode(POC_MOVFF,
3775 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3776                 }
3777                 if(size>2) {
3778                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3779 //                      pic16_emitpcode(POC_MOVFF,
3780 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3781                 }
3782                 if(size>1) {
3783                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3784 //                      pic16_emitpcode(POC_MOVFF,
3785 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3786                 }
3787
3788 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3789
3790                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3791 //              pic16_emitpcode(POC_MOVFF,
3792 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3793
3794         } else {
3795                 /* >32-bits, setup stack and FSR0 */
3796                 while (size--) {
3797 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3798 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3799
3800                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3801
3802 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3803                         GpsuedoStkPtr++;
3804                 }
3805                         
3806                 /* setup FSR0 */
3807                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3808                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3809
3810                 if(STACK_MODEL_LARGE) {
3811                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3812                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3813                 } else {
3814                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3815                 }
3816         }
3817                                 
3818 #if 0
3819         /* old code, left here for reference -- VR */    
3820         while (size--) {
3821           char *l ;
3822
3823                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3824                         /* #NOCHANGE */
3825                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3826                         pic16_emitpcomment("push %s",l);
3827                         pushed++;
3828                 } else {
3829                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3830                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3831                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3832                         
3833                         if (strcmp(fReturn[offset],l)) {
3834                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3835                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3836                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3837                                 } else {
3838                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3839                                 }
3840                                 
3841                                 if(size) {
3842                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3843                                 }
3844                                 offset++;
3845                         }
3846                 }
3847         }    
3848
3849         if (pushed) {
3850                 while(pushed) {
3851                         pushed--;
3852                         if (strcmp(fReturn[pushed],"a"))
3853                                 pic16_emitcode("pop",fReturn[pushed]);
3854                         else
3855                                 pic16_emitcode("pop","acc");
3856                 }
3857         }
3858 #endif
3859
3860
3861         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3862     
3863 jumpret:
3864         /* generate a jump to the return label
3865          * if the next is not the return statement */
3866         if (!(ic->next && ic->next->op == LABEL
3867                 && IC_LABEL(ic->next) == returnLabel)) {
3868         
3869                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3870                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3871         }
3872 }
3873
3874 /*-----------------------------------------------------------------*/
3875 /* genLabel - generates a label                                    */
3876 /*-----------------------------------------------------------------*/
3877 static void genLabel (iCode *ic)
3878 {
3879
3880
3881     /* special case never generate */
3882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3883     if (IC_LABEL(ic) == entryLabel)
3884         return ;
3885
3886     pic16_emitpLabel(IC_LABEL(ic)->key);
3887     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3888 }
3889
3890 /*-----------------------------------------------------------------*/
3891 /* genGoto - generates a goto                                      */
3892 /*-----------------------------------------------------------------*/
3893 //tsd
3894 static void genGoto (iCode *ic)
3895 {
3896   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3897   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3898 }
3899
3900
3901 /*-----------------------------------------------------------------*/
3902 /* genMultbits :- multiplication of bits                           */
3903 /*-----------------------------------------------------------------*/
3904 static void genMultbits (operand *left, 
3905                          operand *right, 
3906                          operand *result)
3907 {
3908   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3909
3910   if(!pic16_sameRegs(AOP(result),AOP(right)))
3911     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3912
3913   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3914   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3915   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3916
3917 }
3918
3919
3920 /*-----------------------------------------------------------------*/
3921 /* genMultOneByte : 8 bit multiplication & division                */
3922 /*-----------------------------------------------------------------*/
3923 static void genMultOneByte (operand *left,
3924                             operand *right,
3925                             operand *result)
3926 {
3927
3928   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3929   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3930   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3931
3932   /* (if two literals, the value is computed before) */
3933   /* if one literal, literal on the right */
3934   if (AOP_TYPE(left) == AOP_LIT){
3935     operand *t = right;
3936     right = left;
3937     left = t;
3938   }
3939
3940         /* size is already checked in genMult == 1 */
3941 //      size = AOP_SIZE(result);
3942
3943         if (AOP_TYPE(right) == AOP_LIT){
3944                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3945                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3946                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3947                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3948         } else {
3949                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3950                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3951                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3952                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3953         }
3954         
3955         pic16_genMult8X8_8 (left, right,result);
3956 }
3957
3958 /*-----------------------------------------------------------------*/
3959 /* genMultOneWord : 16 bit multiplication                          */
3960 /*-----------------------------------------------------------------*/
3961 static void genMultOneWord (operand *left,
3962                             operand *right,
3963                             operand *result)
3964 {
3965
3966         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3967         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3968         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3969
3970         /* (if two literals, the value is computed before)
3971          * if one literal, literal on the right */
3972         if (AOP_TYPE(left) == AOP_LIT){
3973           operand *t = right;
3974                 right = left;
3975                 left = t;
3976         }
3977
3978         /* size is checked already == 2 */
3979 //      size = AOP_SIZE(result);
3980
3981         if (AOP_TYPE(right) == AOP_LIT) {
3982                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3983                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3984                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3985                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3986         } else {
3987                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3988                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3989                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3990                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3991         }
3992         
3993         pic16_genMult16X16_16(left, right,result);
3994 }
3995
3996 /*-----------------------------------------------------------------*/
3997 /* genMultOneLong : 32 bit multiplication                          */
3998 /*-----------------------------------------------------------------*/
3999 static void genMultOneLong (operand *left,
4000                             operand *right,
4001                             operand *result)
4002 {
4003
4004         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4005         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4006         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4007
4008         /* (if two literals, the value is computed before)
4009          * if one literal, literal on the right */
4010         if (AOP_TYPE(left) == AOP_LIT){
4011           operand *t = right;
4012                 right = left;
4013                 left = t;
4014         }
4015
4016         /* size is checked already == 4 */
4017 //      size = AOP_SIZE(result);
4018
4019         if (AOP_TYPE(right) == AOP_LIT) {
4020                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4021                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4022                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4023                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4024         } else {
4025                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4026                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4027                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4028                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4029         }
4030         
4031         pic16_genMult32X32_32(left, right,result);
4032 }
4033
4034
4035
4036 /*-----------------------------------------------------------------*/
4037 /* genMult - generates code for multiplication                     */
4038 /*-----------------------------------------------------------------*/
4039 static void genMult (iCode *ic)
4040 {
4041   operand *left = IC_LEFT(ic);
4042   operand *right = IC_RIGHT(ic);
4043   operand *result= IC_RESULT(ic);   
4044
4045         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4046         /* assign the amsops */
4047         pic16_aopOp (left,ic,FALSE);
4048         pic16_aopOp (right,ic,FALSE);
4049         pic16_aopOp (result,ic,TRUE);
4050
4051         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4052
4053         /* special cases first *
4054         * both are bits */
4055         if (AOP_TYPE(left) == AOP_CRY
4056                 && AOP_TYPE(right)== AOP_CRY) {
4057                 genMultbits(left,right,result);
4058           goto release ;
4059         }
4060
4061         /* if both are of size == 1 */
4062         if(AOP_SIZE(left) == 1
4063                 && AOP_SIZE(right) == 1) {
4064                 genMultOneByte(left,right,result);
4065           goto release ;
4066         }
4067
4068         /* if both are of size == 2 */
4069         if(AOP_SIZE(left) == 2
4070                 && AOP_SIZE(right) == 2) {
4071                 genMultOneWord(left, right, result);
4072           goto release;
4073         }
4074         
4075         /* if both are of size == 4 */
4076         if(AOP_SIZE(left) == 4
4077                 && AOP_SIZE(right) == 4) {
4078                 genMultOneLong(left, right, result);
4079           goto release;
4080         }
4081         
4082         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4083
4084
4085         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4086         /* should have been converted to function call */
4087         assert(0) ;
4088
4089 release :
4090         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4091         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4092         pic16_freeAsmop(result,NULL,ic,TRUE); 
4093 }
4094
4095 /*-----------------------------------------------------------------*/
4096 /* genDivbits :- division of bits                                  */
4097 /*-----------------------------------------------------------------*/
4098 static void genDivbits (operand *left, 
4099                         operand *right, 
4100                         operand *result)
4101 {
4102
4103     char *l;
4104
4105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4106     /* the result must be bit */    
4107     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4108     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4109
4110     MOVA(l);    
4111
4112     pic16_emitcode("div","ab");
4113     pic16_emitcode("rrc","a");
4114     pic16_aopPut(AOP(result),"c",0);
4115 }
4116
4117 /*-----------------------------------------------------------------*/
4118 /* genDivOneByte : 8 bit division                                  */
4119 /*-----------------------------------------------------------------*/
4120 static void genDivOneByte (operand *left,
4121                            operand *right,
4122                            operand *result)
4123 {
4124     sym_link *opetype = operandType(result);
4125     char *l ;
4126     symbol *lbl ;
4127     int size,offset;
4128
4129         /* result = divident / divisor
4130          * - divident may be a register or a literal,
4131          * - divisor may be a register or a literal,
4132          * so there are 3 cases (literal / literal is optimized
4133          * by the front-end) to handle.
4134          * In addition we must handle signed and unsigned, which
4135          * result in 6 final different cases -- VR */
4136
4137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4138     size = AOP_SIZE(result) - 1;
4139     offset = 1;
4140     /* signed or unsigned */
4141     if (SPEC_USIGN(opetype)) {
4142       pCodeOp *pct1,    /* count */
4143                 *pct2,  /* reste */
4144                 *pct3;  /* temp */
4145       symbol *label1, *label2, *label3;;
4146
4147
4148         /* unsigned is easy */
4149
4150         pct1 = pic16_popGetTempReg(1);
4151         pct2 = pic16_popGetTempReg(1);
4152         pct3 = pic16_popGetTempReg(1);
4153         
4154         label1 = newiTempLabel(NULL);
4155         label2 = newiTempLabel(NULL);
4156         label3 = newiTempLabel(NULL);
4157
4158         /* the following algorithm is extracted from divuint.c */
4159
4160         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4161         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4162         
4163         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4164
4165         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4166         
4167         pic16_emitpLabel(label1->key);
4168         
4169         emitCLRC;
4170         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4171
4172
4173         emitCLRC;
4174         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4175         
4176
4177         emitSKPNC;
4178         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4179         
4180         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4181         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4182         
4183         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4184         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4185         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4186         
4187         pic16_emitpLabel( label3->key );
4188         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4189         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4190         
4191         
4192
4193         pic16_emitpLabel(label2->key);
4194         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4195         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4196         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4197         
4198         /* result is in wreg */
4199         if(AOP_TYPE(result) != AOP_ACC)
4200                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4201
4202         pic16_popReleaseTempReg( pct3, 1);
4203         pic16_popReleaseTempReg( pct2, 1);
4204         pic16_popReleaseTempReg( pct1, 1);
4205
4206         return ;
4207     }
4208
4209     /* signed is a little bit more difficult */
4210
4211     /* save the signs of the operands */
4212     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4213     MOVA(l);    
4214     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4215     pic16_emitcode("push","acc"); /* save it on the stack */
4216
4217     /* now sign adjust for both left & right */
4218     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4219     MOVA(l);       
4220     lbl = newiTempLabel(NULL);
4221     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4222     pic16_emitcode("cpl","a");   
4223     pic16_emitcode("inc","a");
4224     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4225     pic16_emitcode("mov","b,a");
4226
4227     /* sign adjust left side */
4228     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4229     MOVA(l);
4230
4231     lbl = newiTempLabel(NULL);
4232     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4233     pic16_emitcode("cpl","a");
4234     pic16_emitcode("inc","a");
4235     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4236
4237     /* now the division */
4238     pic16_emitcode("div","ab");
4239     /* we are interested in the lower order
4240     only */
4241     pic16_emitcode("mov","b,a");
4242     lbl = newiTempLabel(NULL);
4243     pic16_emitcode("pop","acc");   
4244     /* if there was an over flow we don't 
4245     adjust the sign of the result */
4246     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4247     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4248     CLRC;
4249     pic16_emitcode("clr","a");
4250     pic16_emitcode("subb","a,b");
4251     pic16_emitcode("mov","b,a");
4252     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4253
4254     /* now we are done */
4255     pic16_aopPut(AOP(result),"b",0);
4256     if(size > 0){
4257         pic16_emitcode("mov","c,b.7");
4258         pic16_emitcode("subb","a,acc");   
4259     }
4260     while (size--)
4261         pic16_aopPut(AOP(result),"a",offset++);
4262
4263 }
4264
4265 /*-----------------------------------------------------------------*/
4266 /* genDiv - generates code for division                            */
4267 /*-----------------------------------------------------------------*/
4268 static void genDiv (iCode *ic)
4269 {
4270     operand *left = IC_LEFT(ic);
4271     operand *right = IC_RIGHT(ic);
4272     operand *result= IC_RESULT(ic);   
4273
4274
4275         /* Division is a very lengthy algorithm, so it is better
4276          * to call support routines than inlining algorithm.
4277          * Division functions written here just in case someone
4278          * wants to inline and not use the support libraries -- VR */
4279
4280     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4281     /* assign the amsops */
4282     pic16_aopOp (left,ic,FALSE);
4283     pic16_aopOp (right,ic,FALSE);
4284     pic16_aopOp (result,ic,TRUE);
4285
4286     /* special cases first */
4287     /* both are bits */
4288     if (AOP_TYPE(left) == AOP_CRY &&
4289         AOP_TYPE(right)== AOP_CRY) {
4290         genDivbits(left,right,result);
4291         goto release ;
4292     }
4293
4294     /* if both are of size == 1 */
4295     if (AOP_SIZE(left) == 1 &&
4296         AOP_SIZE(right) == 1 ) {
4297         genDivOneByte(left,right,result);
4298         goto release ;
4299     }
4300
4301     /* should have been converted to function call */
4302     assert(0);
4303 release :
4304     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4305     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4306     pic16_freeAsmop(result,NULL,ic,TRUE); 
4307 }
4308
4309 /*-----------------------------------------------------------------*/
4310 /* genModbits :- modulus of bits                                   */
4311 /*-----------------------------------------------------------------*/
4312 static void genModbits (operand *left, 
4313                         operand *right, 
4314                         operand *result)
4315 {
4316
4317     char *l;
4318
4319     /* the result must be bit */    
4320     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4321     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4322
4323     MOVA(l);       
4324
4325     pic16_emitcode("div","ab");
4326     pic16_emitcode("mov","a,b");
4327     pic16_emitcode("rrc","a");
4328     pic16_aopPut(AOP(result),"c",0);
4329 }
4330
4331 /*-----------------------------------------------------------------*/
4332 /* genModOneByte : 8 bit modulus                                   */
4333 /*-----------------------------------------------------------------*/
4334 static void genModOneByte (operand *left,
4335                            operand *right,
4336                            operand *result)
4337 {
4338     sym_link *opetype = operandType(result);
4339     char *l ;
4340     symbol *lbl ;
4341
4342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4343     /* signed or unsigned */
4344     if (SPEC_USIGN(opetype)) {
4345         /* unsigned is easy */
4346         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4347         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4348         MOVA(l);    
4349         pic16_emitcode("div","ab");
4350         pic16_aopPut(AOP(result),"b",0);
4351         return ;
4352     }
4353
4354     /* signed is a little bit more difficult */
4355
4356     /* save the signs of the operands */
4357     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4358     MOVA(l);
4359
4360     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4361     pic16_emitcode("push","acc"); /* save it on the stack */
4362
4363     /* now sign adjust for both left & right */
4364     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4365     MOVA(l);
4366
4367     lbl = newiTempLabel(NULL);
4368     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4369     pic16_emitcode("cpl","a");   
4370     pic16_emitcode("inc","a");
4371     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4372     pic16_emitcode("mov","b,a"); 
4373
4374     /* sign adjust left side */
4375     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4376     MOVA(l);
4377
4378     lbl = newiTempLabel(NULL);
4379     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4380     pic16_emitcode("cpl","a");   
4381     pic16_emitcode("inc","a");
4382     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4383
4384     /* now the multiplication */
4385     pic16_emitcode("div","ab");
4386     /* we are interested in the lower order
4387     only */
4388     lbl = newiTempLabel(NULL);
4389     pic16_emitcode("pop","acc");   
4390     /* if there was an over flow we don't 
4391     adjust the sign of the result */
4392     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4393     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4394     CLRC ;
4395     pic16_emitcode("clr","a");
4396     pic16_emitcode("subb","a,b");
4397     pic16_emitcode("mov","b,a");
4398     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4399
4400     /* now we are done */
4401     pic16_aopPut(AOP(result),"b",0);
4402
4403 }
4404
4405 /*-----------------------------------------------------------------*/
4406 /* genMod - generates code for division                            */
4407 /*-----------------------------------------------------------------*/
4408 static void genMod (iCode *ic)
4409 {
4410     operand *left = IC_LEFT(ic);
4411     operand *right = IC_RIGHT(ic);
4412     operand *result= IC_RESULT(ic);  
4413
4414     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4415     /* assign the amsops */
4416     pic16_aopOp (left,ic,FALSE);
4417     pic16_aopOp (right,ic,FALSE);
4418     pic16_aopOp (result,ic,TRUE);
4419
4420     /* special cases first */
4421     /* both are bits */
4422     if (AOP_TYPE(left) == AOP_CRY &&
4423         AOP_TYPE(right)== AOP_CRY) {
4424         genModbits(left,right,result);
4425         goto release ;
4426     }
4427
4428     /* if both are of size == 1 */
4429     if (AOP_SIZE(left) == 1 &&
4430         AOP_SIZE(right) == 1 ) {
4431         genModOneByte(left,right,result);
4432         goto release ;
4433     }
4434
4435     /* should have been converted to function call */
4436     assert(0);
4437
4438 release :
4439     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441     pic16_freeAsmop(result,NULL,ic,TRUE); 
4442 }
4443
4444 /*-----------------------------------------------------------------*/
4445 /* genIfxJump :- will create a jump depending on the ifx           */
4446 /*-----------------------------------------------------------------*/
4447 /*
4448   note: May need to add parameter to indicate when a variable is in bit space.
4449 */
4450 static void genIfxJump (iCode *ic, char *jval)
4451 {
4452
4453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4454     /* if true label then we jump if condition
4455     supplied is true */
4456     if ( IC_TRUE(ic) ) {
4457
4458         if(strcmp(jval,"a") == 0)
4459           emitSKPZ;
4460         else if (strcmp(jval,"c") == 0)
4461           emitSKPC;
4462         else {
4463           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4464           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4465         }
4466
4467         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4468         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4469
4470     }
4471     else {
4472         /* false label is present */
4473         if(strcmp(jval,"a") == 0)
4474           emitSKPNZ;
4475         else if (strcmp(jval,"c") == 0)
4476           emitSKPNC;
4477         else {
4478           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4479           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4480         }
4481
4482         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4483         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4484
4485     }
4486
4487
4488     /* mark the icode as generated */
4489     ic->generated = 1;
4490 }
4491
4492 #if 0
4493 // not needed ATM
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genSkip                                                         */
4497 /*-----------------------------------------------------------------*/
4498 static void genSkip(iCode *ifx,int status_bit)
4499 {
4500   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4501   if(!ifx)
4502     return;
4503
4504   if ( IC_TRUE(ifx) ) {
4505     switch(status_bit) {
4506     case 'z':
4507       emitSKPNZ;
4508       break;
4509
4510     case 'c':
4511       emitSKPNC;
4512       break;
4513
4514     case 'd':
4515       emitSKPDC;
4516       break;
4517
4518     }
4519
4520     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4521     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4522
4523   } else {
4524
4525     switch(status_bit) {
4526
4527     case 'z':
4528       emitSKPZ;
4529       break;
4530
4531     case 'c':
4532       emitSKPC;
4533       break;
4534
4535     case 'd':
4536       emitSKPDC;
4537       break;
4538     }
4539     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4540     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4541
4542   }
4543
4544 }
4545 #endif
4546
4547 /*-----------------------------------------------------------------*/
4548 /* genSkipc                                                        */
4549 /*-----------------------------------------------------------------*/
4550 static void genSkipc(resolvedIfx *rifx)
4551 {
4552   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4553   
4554   if(!rifx)
4555     return;
4556
4557   if(rifx->condition)
4558     emitSKPC;
4559   else
4560     emitSKPNC;
4561
4562   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4563   rifx->generated = 1;
4564 }
4565
4566 /*-----------------------------------------------------------------*/
4567 /* genSkipz2                                                       */
4568 /*-----------------------------------------------------------------*/
4569 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4570 {
4571   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4572   
4573   if(!rifx)
4574     return;
4575
4576   if( (rifx->condition ^ invert_condition) & 1)
4577     emitSKPZ;
4578   else
4579     emitSKPNZ;
4580
4581   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4582   rifx->generated = 1;
4583 }
4584
4585 #if 0
4586 /*-----------------------------------------------------------------*/
4587 /* genSkipz                                                        */
4588 /*-----------------------------------------------------------------*/
4589 static void genSkipz(iCode *ifx, int condition)
4590 {
4591   if(!ifx)
4592     return;
4593
4594   if(condition)
4595     emitSKPNZ;
4596   else
4597     emitSKPZ;
4598
4599   if ( IC_TRUE(ifx) )
4600     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4601   else
4602     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4603
4604   if ( IC_TRUE(ifx) )
4605     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4606   else
4607     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4608
4609 }
4610 #endif
4611
4612 /*-----------------------------------------------------------------*/
4613 /* genSkipCond                                                     */
4614 /*-----------------------------------------------------------------*/
4615 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4616 {
4617   if(!rifx)
4618     return;
4619
4620   if(rifx->condition)
4621     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4622   else
4623     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4624
4625
4626   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4627   rifx->generated = 1;
4628 }
4629
4630 #if 0
4631 /*-----------------------------------------------------------------*/
4632 /* genChkZeroes :- greater or less than comparison                 */
4633 /*     For each byte in a literal that is zero, inclusive or the   */
4634 /*     the corresponding byte in the operand with W                */
4635 /*     returns true if any of the bytes are zero                   */
4636 /*-----------------------------------------------------------------*/
4637 static int genChkZeroes(operand *op, int lit,  int size)
4638 {
4639
4640   int i;
4641   int flag =1;
4642
4643   while(size--) {
4644     i = (lit >> (size*8)) & 0xff;
4645
4646     if(i==0) {
4647       if(flag) 
4648         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4649       else
4650         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4651       flag = 0;
4652     }
4653   }
4654
4655   return (flag==0);
4656 }
4657 #endif
4658
4659 /*-----------------------------------------------------------------*/
4660 /* genCmp :- greater or less than comparison                       */
4661 /*-----------------------------------------------------------------*/
4662 #if 1
4663 static void genCmp (operand *left,operand *right,
4664                     operand *result, iCode *ifx, int sign)
4665 {
4666   int size; //, offset = 0 ;
4667   unsigned long lit = 0L,i = 0;
4668   resolvedIfx rFalseIfx;
4669   //  resolvedIfx rTrueIfx;
4670   symbol *truelbl;
4671   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4672 /*
4673   if(ifx) {
4674     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4675     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4676   }
4677 */
4678
4679   resolveIfx(&rFalseIfx,ifx);
4680   truelbl  = newiTempLabel(NULL);
4681   size = max(AOP_SIZE(left),AOP_SIZE(right));
4682
4683   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4684
4685 #define _swapp
4686
4687   /* if literal is on the right then swap with left */
4688   if ((AOP_TYPE(right) == AOP_LIT)) {
4689     operand *tmp = right ;
4690     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4691     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4692 #ifdef _swapp
4693
4694     lit = (lit - 1) & mask;
4695     right = left;
4696     left = tmp;
4697     rFalseIfx.condition ^= 1;
4698 #endif
4699
4700   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4701     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4702   }
4703
4704
4705   //if(IC_TRUE(ifx) == NULL)
4706   /* if left & right are bit variables */
4707   if (AOP_TYPE(left) == AOP_CRY &&
4708       AOP_TYPE(right) == AOP_CRY ) {
4709     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4710     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4711   } else {
4712     /* subtract right from left if at the
4713        end the carry flag is set then we know that
4714        left is greater than right */
4715
4716     symbol *lbl  = newiTempLabel(NULL);
4717
4718 #if 0
4719         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4720                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4721 #endif
4722
4723 #ifndef _swapp
4724     if(AOP_TYPE(right) == AOP_LIT) {
4725
4726       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4727
4728       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4729
4730       /* special cases */
4731
4732       if(lit == 0) {
4733
4734         if(sign != 0) 
4735           genSkipCond(&rFalseIfx,left,size-1,7);
4736         else 
4737           /* no need to compare to 0...*/
4738           /* NOTE: this is a de-generate compare that most certainly 
4739            *       creates some dead code. */
4740           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4741
4742         if(ifx) ifx->generated = 1;
4743         return;
4744
4745       }
4746       size--;
4747
4748       if(size == 0) {
4749         //i = (lit >> (size*8)) & 0xff;
4750         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4751         
4752         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4753
4754         i = ((0-lit) & 0xff);
4755         if(sign) {
4756           if( i == 0x81) { 
4757             /* lit is 0x7f, all signed chars are less than
4758              * this except for 0x7f itself */
4759             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4760             genSkipz2(&rFalseIfx,0);
4761           } else {
4762             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4763             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4764             genSkipc(&rFalseIfx);
4765           }
4766
4767         } else {
4768           if(lit == 1) {
4769             genSkipz2(&rFalseIfx,1);
4770           } else {
4771             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4772             genSkipc(&rFalseIfx);
4773           }
4774         }
4775
4776         if(ifx) ifx->generated = 1;
4777         return;
4778       }
4779
4780       /* chars are out of the way. now do ints and longs */
4781
4782
4783       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4784         
4785       /* special cases */
4786
4787       if(sign) {
4788
4789         if(lit == 0) {
4790           genSkipCond(&rFalseIfx,left,size,7);
4791           if(ifx) ifx->generated = 1;
4792           return;
4793         }
4794
4795         if(lit <0x100) {
4796           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4797
4798           //rFalseIfx.condition ^= 1;
4799           //genSkipCond(&rFalseIfx,left,size,7);
4800           //rFalseIfx.condition ^= 1;
4801
4802           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4803           if(rFalseIfx.condition)
4804             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4805           else
4806             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4807
4808           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4809           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4810           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4811
4812           while(size > 1)
4813             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4814
4815           if(rFalseIfx.condition) {
4816             emitSKPZ;
4817             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4818
4819           } else {
4820             emitSKPNZ;
4821           }
4822
4823           genSkipc(&rFalseIfx);
4824           pic16_emitpLabel(truelbl->key);
4825           if(ifx) ifx->generated = 1;
4826           return;
4827
4828         }
4829
4830         if(size == 1) {
4831
4832           if( (lit & 0xff) == 0) {
4833             /* lower byte is zero */
4834             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4835             i = ((lit >> 8) & 0xff) ^0x80;
4836             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4837             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4838             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4839             genSkipc(&rFalseIfx);
4840
4841
4842             if(ifx) ifx->generated = 1;
4843             return;
4844
4845           }
4846         } else {
4847           /* Special cases for signed longs */
4848           if( (lit & 0xffffff) == 0) {
4849             /* lower byte is zero */
4850             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4851             i = ((lit >> 8*3) & 0xff) ^0x80;
4852             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4853             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4854             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4855             genSkipc(&rFalseIfx);
4856
4857
4858             if(ifx) ifx->generated = 1;
4859             return;
4860
4861           }
4862
4863         }
4864
4865
4866         if(lit & (0x80 << (size*8))) {
4867           /* lit is negative */
4868           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4869
4870           //genSkipCond(&rFalseIfx,left,size,7);
4871
4872           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4873
4874           if(rFalseIfx.condition)
4875             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4876           else
4877             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4878
4879
4880         } else {
4881           /* lit is positive */
4882           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4883           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4884           if(rFalseIfx.condition)
4885             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4886           else
4887             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4888
4889         }
4890
4891         /*
4892           This works, but is only good for ints.
4893           It also requires a "known zero" register.
4894           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4895           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4896           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4897           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4898           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4899           genSkipc(&rFalseIfx);
4900
4901           pic16_emitpLabel(truelbl->key);
4902           if(ifx) ifx->generated = 1;
4903           return;
4904         **/
4905           
4906         /* There are no more special cases, so perform a general compare */
4907   
4908         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4909         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4910
4911         while(size--) {
4912
4913           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4914           emitSKPNZ;
4915           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4916         }
4917         //rFalseIfx.condition ^= 1;
4918         genSkipc(&rFalseIfx);
4919
4920         pic16_emitpLabel(truelbl->key);
4921
4922         if(ifx) ifx->generated = 1;
4923         return;
4924
4925
4926       }
4927
4928
4929       /* sign is out of the way. So now do an unsigned compare */
4930       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4931
4932
4933       /* General case - compare to an unsigned literal on the right.*/
4934
4935       i = (lit >> (size*8)) & 0xff;
4936       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4937       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4938       while(size--) {
4939         i = (lit >> (size*8)) & 0xff;
4940
4941         if(i) {
4942           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4943           emitSKPNZ;
4944           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4945         } else {
4946           /* this byte of the lit is zero, 
4947            *if it's not the last then OR in the variable */
4948           if(size)
4949             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4950         }
4951       }
4952
4953
4954       pic16_emitpLabel(lbl->key);
4955 //      pic16_emitpLabel(truelbl->key);
4956       //if(emitFinalCheck)
4957       genSkipc(&rFalseIfx);
4958       if(sign)
4959         pic16_emitpLabel(truelbl->key);
4960
4961       if(ifx) ifx->generated = 1;
4962       return;
4963
4964
4965     }
4966 #endif  // _swapp
4967
4968     if(AOP_TYPE(left) == AOP_LIT) {
4969       //symbol *lbl = newiTempLabel(NULL);
4970
4971       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4972
4973
4974       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4975
4976       /* Special cases */
4977       if((lit == 0) && (sign == 0)){
4978
4979         size--;
4980         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4981         while(size) 
4982           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4983
4984         genSkipz2(&rFalseIfx,0);
4985         if(ifx) ifx->generated = 1;
4986         return;
4987       }
4988
4989       if(size==1) {
4990         /* Special cases */
4991         lit &= 0xff;
4992         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4993           /* degenerate compare can never be true */
4994           if(rFalseIfx.condition == 0)
4995             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4996
4997           if(ifx) ifx->generated = 1;
4998           return;
4999         }
5000
5001         if(sign) {
5002           /* signed comparisons to a literal byte */
5003
5004           int lp1 = (lit+1) & 0xff;
5005
5006           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5007           switch (lp1) {
5008           case 0:
5009             rFalseIfx.condition ^= 1;
5010             genSkipCond(&rFalseIfx,right,0,7);
5011             break;
5012           case 0x7f:
5013             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5014             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5015             genSkipz2(&rFalseIfx,1);
5016             break;
5017           default:
5018             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5019             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5020             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5021             rFalseIfx.condition ^= 1;
5022             genSkipc(&rFalseIfx);
5023             break;
5024           }
5025         } else {
5026           /* unsigned comparisons to a literal byte */
5027
5028           switch(lit & 0xff ) {
5029           case 0:
5030             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5031             genSkipz2(&rFalseIfx,0);
5032             break;
5033           case 0x7f:
5034             rFalseIfx.condition ^= 1;
5035             genSkipCond(&rFalseIfx,right,0,7);
5036             break;
5037
5038           default:
5039             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5040             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5041             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5042             rFalseIfx.condition ^= 1;
5043             if (AOP_TYPE(result) == AOP_CRY)
5044               genSkipc(&rFalseIfx);
5045             else {
5046               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5047               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5048             }         
5049             break;
5050           }
5051         }
5052
5053         if(ifx) ifx->generated = 1;
5054         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5055                 goto check_carry;
5056         return;
5057
5058       } else {
5059
5060         /* Size is greater than 1 */
5061
5062         if(sign) {
5063           int lp1 = lit+1;
5064
5065           size--;
5066
5067           if(lp1 == 0) {
5068             /* this means lit = 0xffffffff, or -1 */
5069
5070
5071             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5072             rFalseIfx.condition ^= 1;
5073             genSkipCond(&rFalseIfx,right,size,7);
5074             if(ifx) ifx->generated = 1;
5075
5076             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5077               goto check_carry;
5078
5079             return;
5080           }
5081
5082           if(lit == 0) {
5083             int s = size;
5084
5085             if(rFalseIfx.condition) {
5086               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5087               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5088             }
5089
5090             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5091             while(size--)
5092               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5093
5094
5095             emitSKPZ;
5096             if(rFalseIfx.condition) {
5097               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5098               pic16_emitpLabel(truelbl->key);
5099             }else {
5100               rFalseIfx.condition ^= 1;
5101               genSkipCond(&rFalseIfx,right,s,7);
5102             }
5103
5104             if(ifx) ifx->generated = 1;
5105
5106             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5107               goto check_carry;
5108
5109             return;
5110           }
5111
5112           if((size == 1) &&  (0 == (lp1&0xff))) {
5113             /* lower byte of signed word is zero */
5114             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5115             i = ((lp1 >> 8) & 0xff) ^0x80;
5116             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5117             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5118             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5119             rFalseIfx.condition ^= 1;
5120             genSkipc(&rFalseIfx);
5121
5122
5123             if(ifx) ifx->generated = 1;
5124
5125             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5126               goto check_carry;
5127
5128             return;
5129           }
5130
5131           if(lit & (0x80 << (size*8))) {
5132             /* Lit is less than zero */
5133             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5134             //rFalseIfx.condition ^= 1;
5135             //genSkipCond(&rFalseIfx,left,size,7);
5136             //rFalseIfx.condition ^= 1;
5137             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5138             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5139
5140             if(rFalseIfx.condition)
5141               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5142             else
5143               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5144
5145
5146           } else {
5147             /* Lit is greater than or equal to zero */
5148             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5149             //rFalseIfx.condition ^= 1;
5150             //genSkipCond(&rFalseIfx,right,size,7);
5151             //rFalseIfx.condition ^= 1;
5152
5153             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5154             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5155
5156             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5157             if(rFalseIfx.condition)
5158               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5159             else
5160               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5161
5162           }
5163
5164
5165           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5166           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5167
5168           while(size--) {
5169
5170             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5171             emitSKPNZ;
5172             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5173           }
5174           rFalseIfx.condition ^= 1;
5175           //rFalseIfx.condition = 1;
5176           genSkipc(&rFalseIfx);
5177
5178           pic16_emitpLabel(truelbl->key);
5179
5180           if(ifx) ifx->generated = 1;
5181
5182
5183           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5184             goto check_carry;
5185
5186           return;
5187           // end of if (sign)
5188         } else {
5189
5190           /* compare word or long to an unsigned literal on the right.*/
5191
5192
5193           size--;
5194           if(lit < 0xff) {
5195             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5196             switch (lit) {
5197             case 0:
5198               break; /* handled above */
5199 /*
5200             case 0xff:
5201               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5202               while(size--)
5203                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5204               genSkipz2(&rFalseIfx,0);
5205               break;
5206 */
5207             default:
5208               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5209               while(--size)
5210                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5211
5212               emitSKPZ;
5213               if(rFalseIfx.condition)
5214                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5215               else
5216                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5217
5218
5219               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5220               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5221
5222               rFalseIfx.condition ^= 1;
5223               genSkipc(&rFalseIfx);
5224             }
5225
5226             pic16_emitpLabel(truelbl->key);
5227
5228             if(ifx) ifx->generated = 1;
5229
5230             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5231               goto check_carry;
5232
5233             return;
5234           }
5235
5236
5237           lit++;
5238           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5239           i = (lit >> (size*8)) & 0xff;
5240
5241           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5242           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5243
5244           while(size--) {
5245             i = (lit >> (size*8)) & 0xff;
5246
5247             if(i) {
5248               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5249               emitSKPNZ;
5250               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5251             } else {
5252               /* this byte of the lit is zero, 
5253                * if it's not the last then OR in the variable */
5254               if(size)
5255                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5256             }
5257           }
5258
5259
5260           pic16_emitpLabel(lbl->key);
5261
5262           rFalseIfx.condition ^= 1;
5263
5264           genSkipc(&rFalseIfx);
5265         }
5266
5267         if(sign)
5268           pic16_emitpLabel(truelbl->key);
5269         if(ifx) ifx->generated = 1;
5270
5271             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5272               goto check_carry;
5273
5274         return;
5275       }
5276     }
5277     /* Compare two variables */
5278
5279     DEBUGpic16_emitcode(";sign","%d",sign);
5280
5281     size--;
5282     if(sign) {
5283       /* Sigh. thus sucks... */
5284       if(size) {
5285         pCodeOp *pctemp;
5286         
5287         pctemp = pic16_popGetTempReg(1);
5288         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5289         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5290         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5291         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5292         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5293         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5294         pic16_popReleaseTempReg(pctemp, 1);
5295       } else {
5296         /* Signed char comparison */
5297         /* Special thanks to Nikolai Golovchenko for this snippet */
5298         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5299         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5300         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5301         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5302         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5303         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5304
5305         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5306         genSkipc(&rFalseIfx);
5307           
5308         if(ifx) ifx->generated = 1;
5309
5310             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5311               goto check_carry;
5312
5313         return;
5314       }
5315
5316     } else {
5317
5318       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5319       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5320     }
5321
5322
5323     /* The rest of the bytes of a multi-byte compare */
5324     while (size) {
5325
5326       emitSKPZ;
5327       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5328       size--;
5329
5330       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5331       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5332
5333
5334     }
5335
5336     pic16_emitpLabel(lbl->key);
5337
5338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5339     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5340         (AOP_TYPE(result) == AOP_REG)) {
5341       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5342       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5343     } else {
5344       genSkipc(&rFalseIfx);
5345     }         
5346     //genSkipc(&rFalseIfx);
5347     if(ifx) ifx->generated = 1;
5348
5349
5350             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5351               goto check_carry;
5352
5353     return;
5354
5355   }
5356
5357 check_carry:
5358   if ((AOP_TYPE(result) != AOP_CRY) 
5359         && AOP_SIZE(result)) {
5360     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5361
5362     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5363
5364     pic16_outBitC(result);
5365   } else {
5366     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5367     /* if the result is used in the next
5368        ifx conditional branch then generate
5369        code a little differently */
5370     if (ifx )
5371       genIfxJump (ifx,"c");
5372     else
5373       pic16_outBitC(result);
5374     /* leave the result in acc */
5375   }
5376
5377 }
5378
5379 #else   /* old version of genCmp() */
5380
5381 /* new version of genCmp -- VR 20041012 */
5382 static void genCmp (operand *left,operand *right,
5383                     operand *result, iCode *ifx, int sign)
5384 {
5385   int size; //, offset = 0 ;
5386   unsigned long lit = 0L,i = 0;
5387   resolvedIfx rFalseIfx;
5388   int willCheckCarry=0;
5389   //  resolvedIfx rTrueIfx;
5390   symbol *truelbl;
5391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5392
5393
5394   /* General concept:
5395    * subtract right from left if at the end the carry flag is set then we
5396    * know that left is greater than right */
5397             
5398   resolveIfx(&rFalseIfx,ifx);
5399   truelbl  = newiTempLabel(NULL);
5400   size = max(AOP_SIZE(left),AOP_SIZE(right));
5401
5402   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5403
5404   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5405    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5406   
5407
5408   /* if literal is on the right then swap with left */
5409   if ((AOP_TYPE(right) == AOP_LIT)) {
5410     operand *tmp = right ;
5411     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5412
5413       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5414
5415 //      lit = (lit - 1) & mask;
5416       right = left;
5417       left = tmp;
5418       rFalseIfx.condition ^= 1;
5419   } else
5420   if ((AOP_TYPE(left) == AOP_LIT)) {
5421     /* float compares are handled by support functions */
5422     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5423   }
5424
5425
5426   //if(IC_TRUE(ifx) == NULL)
5427   /* if left & right are bit variables */
5428   if (AOP_TYPE(left) == AOP_CRY &&
5429       AOP_TYPE(right) == AOP_CRY ) {
5430     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5431     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5432
5433   } else {
5434     symbol *lbl  = newiTempLabel(NULL);
5435
5436     if(AOP_TYPE(left) == AOP_LIT) {
5437       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5438
5439       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5440         willCheckCarry = 1;
5441       else willCheckCarry = 0;
5442
5443       /* Special cases */
5444       if((lit == 0) && (sign == 0)){
5445
5446         size--;
5447         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5448         while(size) 
5449           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5450
5451         genSkipz2(&rFalseIfx,0);
5452         if(ifx) ifx->generated = 1;
5453         return;
5454       }
5455
5456       if(size==1) {
5457         /* Special cases */
5458         lit &= 0xff;
5459         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5460           /* degenerate compare can never be true */
5461           if(rFalseIfx.condition == 0)
5462             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5463
5464           if(ifx) ifx->generated = 1;
5465           return;
5466         }
5467
5468         if(sign) {
5469           /* signed comparisons to a literal byte */
5470
5471           int lp1 = (lit+1) & 0xff;
5472
5473           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d",__LINE__,lit, rFalseIfx.condition);
5474           switch (lp1) {
5475           case 0:
5476             rFalseIfx.condition ^= 1;
5477             genSkipCond(&rFalseIfx,right,0,7);
5478             break;
5479           case 0x7f:
5480             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5481             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5482             genSkipz2(&rFalseIfx,1);
5483             break;
5484           default:
5485             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5486             
5487             if(rFalseIfx.condition)
5488               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5489             else
5490               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5491
5492             if(willCheckCarry) {
5493               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5494               else { emitSETC; emitCLRC; }
5495               
5496             } else {
5497               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5498             }              
5499                       
5500 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5501             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5502             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5503             rFalseIfx.condition ^= 1;
5504             genSkipc(&rFalseIfx);
5505 */
5506             break;
5507           }
5508         } else {
5509           /* unsigned comparisons to a literal byte */
5510
5511           switch(lit & 0xff ) {
5512           case 0:
5513             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5514             genSkipz2(&rFalseIfx,0);
5515             break;
5516           case 0x7f:
5517             rFalseIfx.condition ^= 1;
5518             genSkipCond(&rFalseIfx,right,0,7);
5519             break;
5520
5521           default:
5522             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5523             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5524             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5525             rFalseIfx.condition ^= 1;
5526             if (AOP_TYPE(result) == AOP_CRY)
5527               genSkipc(&rFalseIfx);
5528             else {
5529               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5530               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5531             }         
5532             break;
5533           }
5534         }
5535
5536         if(ifx) ifx->generated = 1;
5537         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5538                 goto check_carry;
5539         return;
5540
5541       } else {
5542
5543         /* Size is greater than 1 */
5544
5545         if(sign) {
5546           int lp1 = lit+1;
5547
5548           size--;
5549
5550           if(lp1 == 0) {
5551             /* this means lit = 0xffffffff, or -1 */
5552
5553
5554             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5555             rFalseIfx.condition ^= 1;
5556             genSkipCond(&rFalseIfx,right,size,7);
5557             if(ifx) ifx->generated = 1;
5558             return;
5559           }
5560
5561           if(lit == 0) {
5562             int s = size;
5563
5564             if(rFalseIfx.condition) {
5565               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5566               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5567             }
5568
5569             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5570             while(size--)
5571               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5572
5573
5574             emitSKPZ;
5575             if(rFalseIfx.condition) {
5576               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5577               pic16_emitpLabel(truelbl->key);
5578             }else {
5579               rFalseIfx.condition ^= 1;
5580               genSkipCond(&rFalseIfx,right,s,7);
5581             }
5582
5583             if(ifx) ifx->generated = 1;
5584             return;
5585           }
5586
5587           if((size == 1) &&  (0 == (lp1&0xff))) {
5588             /* lower byte of signed word is zero */
5589             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5590             i = ((lp1 >> 8) & 0xff) ^0x80;
5591             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5592             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5593             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5594             rFalseIfx.condition ^= 1;
5595             genSkipc(&rFalseIfx);
5596
5597
5598             if(ifx) ifx->generated = 1;
5599             return;
5600           }
5601
5602           if(lit & (0x80 << (size*8))) {
5603             /* Lit is less than zero */
5604             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5605             //rFalseIfx.condition ^= 1;
5606             //genSkipCond(&rFalseIfx,left,size,7);
5607             //rFalseIfx.condition ^= 1;
5608             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5609             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5610
5611             if(rFalseIfx.condition)
5612               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5613             else
5614               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5615
5616
5617           } else {
5618             /* Lit is greater than or equal to zero */
5619             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5620             //rFalseIfx.condition ^= 1;
5621             //genSkipCond(&rFalseIfx,right,size,7);
5622             //rFalseIfx.condition ^= 1;
5623
5624             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5625             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5626
5627             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5628             if(rFalseIfx.condition)
5629               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5630             else
5631               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5632
5633           }
5634
5635
5636           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5637           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5638
5639           while(size--) {
5640
5641             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5642             emitSKPNZ;
5643             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5644           }
5645           rFalseIfx.condition ^= 1;
5646           //rFalseIfx.condition = 1;
5647           genSkipc(&rFalseIfx);
5648
5649           pic16_emitpLabel(truelbl->key);
5650
5651           if(ifx) ifx->generated = 1;
5652           return;
5653           // end of if (sign)
5654         } else {
5655
5656           /* compare word or long to an unsigned literal on the right.*/
5657
5658
5659           size--;
5660           if(lit < 0xff) {
5661             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5662             switch (lit) {
5663             case 0:
5664               break; /* handled above */
5665 /*
5666             case 0xff:
5667               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668               while(size--)
5669                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5670               genSkipz2(&rFalseIfx,0);
5671               break;
5672 */
5673             default:
5674               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5675               while(--size)
5676                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5677
5678               emitSKPZ;
5679               if(rFalseIfx.condition)
5680                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681               else
5682                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5686               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5687
5688               rFalseIfx.condition ^= 1;
5689               genSkipc(&rFalseIfx);
5690             }
5691
5692             pic16_emitpLabel(truelbl->key);
5693
5694             if(ifx) ifx->generated = 1;
5695             return;
5696           }
5697
5698
5699           lit++;
5700           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5701           i = (lit >> (size*8)) & 0xff;
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707             i = (lit >> (size*8)) & 0xff;
5708
5709             if(i) {
5710               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5711               emitSKPNZ;
5712               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5713             } else {
5714               /* this byte of the lit is zero, 
5715                * if it's not the last then OR in the variable */
5716               if(size)
5717                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5718             }
5719           }
5720
5721
5722           pic16_emitpLabel(lbl->key);
5723
5724           rFalseIfx.condition ^= 1;
5725
5726           genSkipc(&rFalseIfx);
5727         }
5728
5729         if(sign)
5730           pic16_emitpLabel(truelbl->key);
5731         if(ifx) ifx->generated = 1;
5732         return;
5733       }
5734     }
5735     /* Compare two variables */
5736
5737     DEBUGpic16_emitcode(";sign","%d",sign);
5738
5739     size--;
5740     if(sign) {
5741       /* Sigh. thus sucks... */
5742       if(size) {
5743         pCodeOp *pctemp;
5744         
5745         pctemp = pic16_popGetTempReg(1);
5746         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5747         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5748         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5749         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5750         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5751         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5752         pic16_popReleaseTempReg(pctemp, 1);
5753       } else {
5754         /* Signed char comparison */
5755         /* Special thanks to Nikolai Golovchenko for this snippet */
5756         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5757         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5758         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5759         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5760         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5761         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5762
5763         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5764         genSkipc(&rFalseIfx);
5765           
5766         if(ifx) ifx->generated = 1;
5767         return;
5768       }
5769
5770     } else {
5771
5772       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5773       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5774     }
5775
5776
5777     /* The rest of the bytes of a multi-byte compare */
5778     while (size) {
5779
5780       emitSKPZ;
5781       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5782       size--;
5783
5784       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5785       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5786
5787
5788     }
5789
5790     pic16_emitpLabel(lbl->key);
5791
5792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5793     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5794         (AOP_TYPE(result) == AOP_REG)) {
5795       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5796       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5797     } else {
5798       genSkipc(&rFalseIfx);
5799     }         
5800     //genSkipc(&rFalseIfx);
5801     if(ifx) ifx->generated = 1;
5802
5803     return;
5804
5805   }
5806
5807 check_carry:
5808   if ((AOP_TYPE(result) != AOP_CRY) 
5809         && AOP_SIZE(result)) {
5810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5811
5812     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5813
5814     pic16_outBitC(result);
5815   } else {
5816     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5817     /* if the result is used in the next
5818        ifx conditional branch then generate
5819        code a little differently */
5820     if (ifx )
5821       genIfxJump (ifx,"c");
5822     else
5823       pic16_outBitC(result);
5824     /* leave the result in acc */
5825   }
5826
5827 }
5828 #endif
5829
5830
5831
5832 /*-----------------------------------------------------------------*/
5833 /* genCmpGt :- greater than comparison                             */
5834 /*-----------------------------------------------------------------*/
5835 static void genCmpGt (iCode *ic, iCode *ifx)
5836 {
5837     operand *left, *right, *result;
5838     sym_link *letype , *retype;
5839     int sign ;
5840
5841     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5842     left = IC_LEFT(ic);
5843     right= IC_RIGHT(ic);
5844     result = IC_RESULT(ic);
5845
5846     letype = getSpec(operandType(left));
5847     retype =getSpec(operandType(right));
5848     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5849     /* assign the amsops */
5850     pic16_aopOp (left,ic,FALSE);
5851     pic16_aopOp (right,ic,FALSE);
5852     pic16_aopOp (result,ic,TRUE);
5853
5854     genCmp(right, left, result, ifx, sign);
5855
5856     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5857     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5858     pic16_freeAsmop(result,NULL,ic,TRUE); 
5859 }
5860
5861 /*-----------------------------------------------------------------*/
5862 /* genCmpLt - less than comparisons                                */
5863 /*-----------------------------------------------------------------*/
5864 static void genCmpLt (iCode *ic, iCode *ifx)
5865 {
5866     operand *left, *right, *result;
5867     sym_link *letype , *retype;
5868     int sign ;
5869
5870     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5871     left = IC_LEFT(ic);
5872     right= IC_RIGHT(ic);
5873     result = IC_RESULT(ic);
5874
5875     letype = getSpec(operandType(left));
5876     retype =getSpec(operandType(right));
5877     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5878
5879     /* assign the amsops */
5880     pic16_aopOp (left,ic,FALSE);
5881     pic16_aopOp (right,ic,FALSE);
5882     pic16_aopOp (result,ic,TRUE);
5883
5884     genCmp(left, right, result, ifx, sign);
5885
5886     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5887     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5888     pic16_freeAsmop(result,NULL,ic,TRUE); 
5889 }
5890
5891 #if 0
5892 // not needed ATM
5893 // FIXME reenable literal optimisation when the pic16 port is stable
5894
5895 /*-----------------------------------------------------------------*/
5896 /* genc16bit2lit - compare a 16 bit value to a literal             */
5897 /*-----------------------------------------------------------------*/
5898 static void genc16bit2lit(operand *op, int lit, int offset)
5899 {
5900   int i;
5901
5902   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5903   if( (lit&0xff) == 0) 
5904     i=1;
5905   else
5906     i=0;
5907
5908   switch( BYTEofLONG(lit,i)) { 
5909   case 0:
5910     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5911     break;
5912   case 1:
5913     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5914     break;
5915   case 0xff:
5916     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5917     break;
5918   default:
5919     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5920     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5921   }
5922
5923   i ^= 1;
5924
5925   switch( BYTEofLONG(lit,i)) { 
5926   case 0:
5927     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5928     break;
5929   case 1:
5930     emitSKPNZ;
5931     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5932     break;
5933   case 0xff:
5934     emitSKPNZ;
5935     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5936     break;
5937   default:
5938     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5939     emitSKPNZ;
5940     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5941
5942   }
5943
5944 }
5945 #endif
5946
5947 #if 0
5948 // not needed ATM
5949 /*-----------------------------------------------------------------*/
5950 /* gencjneshort - compare and jump if not equal                    */
5951 /*-----------------------------------------------------------------*/
5952 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5953 {
5954   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5955   int offset = 0;
5956   int res_offset = 0;  /* the result may be a different size then left or right */
5957   int res_size = AOP_SIZE(result);
5958   resolvedIfx rIfx;
5959   symbol *lbl, *lbl_done;
5960
5961   unsigned long lit = 0L;
5962   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5963
5964   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5965   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5966   if(result)
5967     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5968   resolveIfx(&rIfx,ifx);
5969   lbl =  newiTempLabel(NULL);
5970   lbl_done =  newiTempLabel(NULL);
5971
5972
5973   /* if the left side is a literal or 
5974      if the right is in a pointer register and left 
5975      is not */
5976   if ((AOP_TYPE(left) == AOP_LIT) || 
5977       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5978     operand *t = right;
5979     right = left;
5980     left = t;
5981   }
5982   if(AOP_TYPE(right) == AOP_LIT)
5983     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5984
5985   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5986     preserve_result = 1;
5987
5988   if(result && !preserve_result)
5989     {
5990       int i;
5991       for(i = 0; i < AOP_SIZE(result); i++)
5992         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5993     }
5994
5995
5996   /* if the right side is a literal then anything goes */
5997   if (AOP_TYPE(right) == AOP_LIT &&
5998       AOP_TYPE(left) != AOP_DIR ) {
5999     switch(size) {
6000     case 2:
6001       genc16bit2lit(left, lit, 0);
6002       emitSKPZ;
6003       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6004       break;
6005     default:
6006       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6007       while (size--) {
6008         if(lit & 0xff) {
6009           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6010           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6011         } else {
6012           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6013         }
6014
6015         emitSKPZ;
6016         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6017         offset++;
6018         if(res_offset < res_size-1)
6019           res_offset++;
6020         lit >>= 8;
6021       }
6022       break;
6023     }
6024   }
6025
6026   /* if the right side is in a register or in direct space or
6027      if the left is a pointer register & right is not */    
6028   else if (AOP_TYPE(right) == AOP_REG ||
6029            AOP_TYPE(right) == AOP_DIR || 
6030            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6031            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6032     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6033     int lbl_key = lbl->key;
6034
6035     if(result) {
6036       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6037       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6038     }else {
6039       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6040       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6041               __FUNCTION__,__LINE__);
6042       return;
6043     }
6044    
6045 /*     switch(size) { */
6046 /*     case 2: */
6047 /*       genc16bit2lit(left, lit, 0); */
6048 /*       emitSKPNZ; */
6049 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6050 /*       break; */
6051 /*     default: */
6052     while (size--) {
6053       int emit_skip=1;
6054       if((AOP_TYPE(left) == AOP_DIR) && 
6055          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6056
6057         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6058         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6059
6060       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6061             
6062         switch (lit & 0xff) {
6063         case 0:
6064           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6065           break;
6066         case 1:
6067           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6068           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6069           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6070           emit_skip=0;
6071           break;
6072         case 0xff:
6073           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6074           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6075           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6076           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6077           emit_skip=0;
6078           break;
6079         default:
6080           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6081           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6082         }
6083         lit >>= 8;
6084
6085       } else {
6086         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6087       }
6088       if(emit_skip) {
6089         if(AOP_TYPE(result) == AOP_CRY) {
6090           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6091           if(rIfx.condition)
6092             emitSKPNZ;
6093           else
6094             emitSKPZ;
6095           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6096         } else {
6097           /* fix me. probably need to check result size too */
6098           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6099           if(rIfx.condition)
6100             emitSKPZ;
6101           else
6102             emitSKPNZ;
6103           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6104           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6105         }
6106         if(ifx)
6107           ifx->generated=1;
6108       }
6109       emit_skip++;
6110       offset++;
6111       if(res_offset < res_size-1)
6112         res_offset++;
6113     }
6114 /*       break; */
6115 /*     } */
6116   } else if(AOP_TYPE(right) == AOP_REG &&
6117             AOP_TYPE(left) != AOP_DIR){
6118
6119     while(size--) {
6120       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6121       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6122       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6123       if(rIfx.condition)
6124         emitSKPNZ;
6125       else
6126         emitSKPZ;
6127       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6128       offset++;
6129       if(res_offset < res_size-1)
6130         res_offset++;
6131     }
6132       
6133   }else{
6134     /* right is a pointer reg need both a & b */
6135     while(size--) {
6136       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6137       if(strcmp(l,"b"))
6138         pic16_emitcode("mov","b,%s",l);
6139       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6140       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6141       offset++;
6142     }
6143   }
6144
6145   if(result && preserve_result)
6146     {
6147       int i;
6148       for(i = 0; i < AOP_SIZE(result); i++)
6149         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6150     }
6151
6152   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6153
6154   if(result && preserve_result)
6155     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6156
6157   if(!rIfx.condition)
6158     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6159
6160   pic16_emitpLabel(lbl->key);
6161
6162   if(result && preserve_result)
6163     {
6164       int i;
6165       for(i = 0; i < AOP_SIZE(result); i++)
6166         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6167
6168       pic16_emitpLabel(lbl_done->key);
6169    }
6170
6171   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6172
6173   if(ifx)
6174     ifx->generated = 1;
6175 }
6176 #endif
6177
6178 #if 0
6179 /*-----------------------------------------------------------------*/
6180 /* gencjne - compare and jump if not equal                         */
6181 /*-----------------------------------------------------------------*/
6182 static void gencjne(operand *left, operand *right, iCode *ifx)
6183 {
6184     symbol *tlbl  = newiTempLabel(NULL);
6185
6186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6187     gencjneshort(left, right, lbl);
6188
6189     pic16_emitcode("mov","a,%s",one);
6190     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6191     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6192     pic16_emitcode("clr","a");
6193     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6194
6195     pic16_emitpLabel(lbl->key);
6196     pic16_emitpLabel(tlbl->key);
6197
6198 }
6199 #endif
6200
6201
6202 /*-----------------------------------------------------------------*/
6203 /* is_LitOp - check if operand has to be treated as literal        */
6204 /*-----------------------------------------------------------------*/
6205 static bool is_LitOp(operand *op)
6206 {
6207   return (AOP_TYPE(op) == AOP_LIT)
6208       || ( (AOP_TYPE(op) == AOP_PCODE)
6209           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6210               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* is_LitAOp - check if operand has to be treated as literal        */
6215 /*-----------------------------------------------------------------*/
6216 static bool is_LitAOp(asmop *aop)
6217 {
6218   return (aop->type == AOP_LIT)
6219       || ( (aop->type == AOP_PCODE)
6220           && ( (aop->aopu.pcop->type == PO_LITERAL)
6221               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
6222 }
6223
6224
6225
6226 /*-----------------------------------------------------------------*/
6227 /* genCmpEq - generates code for equal to                          */
6228 /*-----------------------------------------------------------------*/
6229 static void genCmpEq (iCode *ic, iCode *ifx)
6230 {
6231   operand *left, *right, *result;
6232   symbol *falselbl = newiTempLabel(NULL);
6233   symbol *donelbl = newiTempLabel(NULL);
6234
6235   int preserve_result = 0;
6236   int generate_result = 0;
6237   int i=0;
6238
6239   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6240   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6241   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6242  
6243   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6244   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6245
6246   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6247     {
6248       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6249       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6250       goto release;
6251     }
6252
6253   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6254     {
6255       operand *tmp = right ;
6256       right = left;
6257       left = tmp;
6258     }
6259
6260   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6261     preserve_result = 1;
6262
6263   if(result && AOP_SIZE(result))
6264     generate_result = 1;
6265
6266   if(generate_result && !preserve_result)
6267     {
6268       for(i = 0; i < AOP_SIZE(result); i++)
6269         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6270     }
6271
6272   for(i=0; i < AOP_SIZE(left); i++)
6273     {
6274       if(AOP_TYPE(left) != AOP_ACC)
6275         {
6276           if(is_LitOp(left))
6277             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6278           else
6279             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6280         }
6281       if(is_LitOp(right))
6282         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6283       else
6284         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6285
6286       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6287     }
6288
6289   // result == true
6290
6291   if(generate_result && preserve_result)
6292     {
6293       for(i = 0; i < AOP_SIZE(result); i++)
6294         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6295     }
6296
6297   if(generate_result)
6298     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6299
6300   if(generate_result && preserve_result)
6301     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6302
6303   if(ifx && IC_TRUE(ifx))
6304     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6305
6306   if(ifx && IC_FALSE(ifx))
6307     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6308
6309   pic16_emitpLabel(falselbl->key);
6310
6311   // result == false
6312
6313   if(ifx && IC_FALSE(ifx))
6314     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6315
6316   if(generate_result && preserve_result)
6317     {
6318       for(i = 0; i < AOP_SIZE(result); i++)
6319         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6320     }
6321
6322   pic16_emitpLabel(donelbl->key);
6323
6324   if(ifx)
6325     ifx->generated = 1;
6326
6327 release:
6328   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330   pic16_freeAsmop(result,NULL,ic,TRUE);
6331
6332 }
6333
6334
6335 #if 0
6336 // old version kept for reference
6337
6338 /*-----------------------------------------------------------------*/
6339 /* genCmpEq - generates code for equal to                          */
6340 /*-----------------------------------------------------------------*/
6341 static void genCmpEq (iCode *ic, iCode *ifx)
6342 {
6343     operand *left, *right, *result;
6344     unsigned long lit = 0L;
6345     int size,offset=0;
6346     symbol *falselbl  = newiTempLabel(NULL);
6347
6348
6349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6350
6351     if(ifx)
6352       DEBUGpic16_emitcode ("; ifx is non-null","");
6353     else
6354       DEBUGpic16_emitcode ("; ifx is null","");
6355
6356     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6357     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6358     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6359
6360     size = max(AOP_SIZE(left),AOP_SIZE(right));
6361
6362     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6363
6364     /* if literal, literal on the right or 
6365     if the right is in a pointer register and left 
6366     is not */
6367     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6368         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6369       operand *tmp = right ;
6370       right = left;
6371       left = tmp;
6372     }
6373
6374
6375     if(ifx && !AOP_SIZE(result)){
6376         symbol *tlbl;
6377         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6378         /* if they are both bit variables */
6379         if (AOP_TYPE(left) == AOP_CRY &&
6380             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6381                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6382             if(AOP_TYPE(right) == AOP_LIT){
6383                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6384                 if(lit == 0L){
6385                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6386                     pic16_emitcode("cpl","c");
6387                 } else if(lit == 1L) {
6388                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6389                 } else {
6390                     pic16_emitcode("clr","c");
6391                 }
6392                 /* AOP_TYPE(right) == AOP_CRY */
6393             } else {
6394                 symbol *lbl = newiTempLabel(NULL);
6395                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6396                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6397                 pic16_emitcode("cpl","c");
6398                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6399             }
6400             /* if true label then we jump if condition
6401             supplied is true */
6402             tlbl = newiTempLabel(NULL);
6403             if ( IC_TRUE(ifx) ) {
6404                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6405                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6406             } else {
6407                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6408                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6409             }
6410             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6411
6412                 {
6413                 /* left and right are both bit variables, result is carry */
6414                         resolvedIfx rIfx;
6415               
6416                         resolveIfx(&rIfx,ifx);
6417
6418                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6419                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6420                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6421                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6422                         genSkipz2(&rIfx,0);
6423                 }
6424         } else {
6425
6426                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6427
6428                         /* They're not both bit variables. Is the right a literal? */
6429                         if(AOP_TYPE(right) == AOP_LIT) {
6430                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6431             
6432                         switch(size) {
6433
6434                                 case 1:
6435                                         switch(lit & 0xff) {
6436                                                 case 1:
6437                                                                 if ( IC_TRUE(ifx) ) {
6438                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6439                                                                         emitSKPNZ;
6440                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6441                                                                 } else {
6442                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6443                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6444                                                                 }
6445                                                                 break;
6446                                                 case 0xff:
6447                                                                 if ( IC_TRUE(ifx) ) {
6448                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6449                                                                         emitSKPNZ;
6450                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6451                                                                 } else {
6452                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6453                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6454                                                                 }
6455                                                                 break;
6456                                                 default:
6457                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458                                                                 if(lit)
6459                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6460                                                                 genSkip(ifx,'z');
6461                                         } // switch lit
6462
6463
6464                                         /* end of size == 1 */
6465                                         break;
6466               
6467                                 case 2:
6468                                         genc16bit2lit(left,lit,offset);
6469                                         genSkip(ifx,'z');
6470                                         break;
6471                                         /* end of size == 2 */
6472
6473                                 default:
6474                                         /* size is 4 */
6475                                         if(lit==0) {
6476                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6477                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6478                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6479                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6480                                                 genSkip(ifx,'z');
6481                                         } else {
6482                                                 /* search for patterns that can be optimized */
6483
6484                                                 genc16bit2lit(left,lit,0);
6485                                                 lit >>= 16;
6486                                                 if(lit) {
6487                                                                 if(IC_TRUE(ifx))
6488                                                                 emitSKPZ; // if hi word unequal
6489                                                                 else
6490                                                                 emitSKPNZ; // if hi word equal
6491                                                                 // fail early
6492                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6493                                                         genc16bit2lit(left,lit,2);
6494                                                         genSkip(ifx,'z');
6495                                                 } else {
6496                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6497                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6498                                                         genSkip(ifx,'z');
6499                                                 }
6500                                         }
6501                                                 pic16_emitpLabel(falselbl->key);
6502                                                 break;
6503
6504                         } // switch size
6505           
6506                         ifx->generated = 1;
6507                         goto release ;
6508             
6509
6510           } else if(AOP_TYPE(right) == AOP_CRY ) {
6511             /* we know the left is not a bit, but that the right is */
6512             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6514                       pic16_popGet(AOP(right),offset));
6515             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6516
6517             /* if the two are equal, then W will be 0 and the Z bit is set
6518              * we could test Z now, or go ahead and check the high order bytes if
6519              * the variable we're comparing is larger than a byte. */
6520
6521             while(--size)
6522               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6523
6524             if ( IC_TRUE(ifx) ) {
6525               emitSKPNZ;
6526               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6527               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6528             } else {
6529               emitSKPZ;
6530               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6531               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6532             }
6533
6534           } else {
6535             /* They're both variables that are larger than bits */
6536             int s = size;
6537
6538             tlbl = newiTempLabel(NULL);
6539
6540             while(size--) {
6541               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6542               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6543
6544               if ( IC_TRUE(ifx) ) {
6545                 if(size) {
6546                   emitSKPZ;
6547                 
6548                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6549
6550                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6551                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6552                 } else {
6553                   emitSKPNZ;
6554
6555                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6556
6557
6558                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6559                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6560                 }
6561               } else {
6562                 emitSKPZ;
6563
6564                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6565
6566                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6567                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6568               }
6569               offset++;
6570             }
6571             if(s>1 && IC_TRUE(ifx)) {
6572               pic16_emitpLabel(tlbl->key);
6573               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6574             }
6575           }
6576         }
6577         /* mark the icode as generated */
6578         ifx->generated = 1;
6579         goto release ;
6580     }
6581
6582     /* if they are both bit variables */
6583     if (AOP_TYPE(left) == AOP_CRY &&
6584         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6585         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6586         if(AOP_TYPE(right) == AOP_LIT){
6587             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6588             if(lit == 0L){
6589                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6590                 pic16_emitcode("cpl","c");
6591             } else if(lit == 1L) {
6592                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6593             } else {
6594                 pic16_emitcode("clr","c");
6595             }
6596             /* AOP_TYPE(right) == AOP_CRY */
6597         } else {
6598             symbol *lbl = newiTempLabel(NULL);
6599             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6600             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6601             pic16_emitcode("cpl","c");
6602             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6603         }
6604         /* c = 1 if egal */
6605         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6606             pic16_outBitC(result);
6607             goto release ;
6608         }
6609         if (ifx) {
6610             genIfxJump (ifx,"c");
6611             goto release ;
6612         }
6613         /* if the result is used in an arithmetic operation
6614         then put the result in place */
6615         pic16_outBitC(result);
6616     } else {
6617       
6618       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6619       gencjne(left,right,result,ifx);
6620 /*
6621       if(ifx) 
6622         gencjne(left,right,newiTempLabel(NULL));
6623       else {
6624         if(IC_TRUE(ifx)->key)
6625           gencjne(left,right,IC_TRUE(ifx)->key);
6626         else
6627           gencjne(left,right,IC_FALSE(ifx)->key);
6628         ifx->generated = 1;
6629         goto release ;
6630       }
6631       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6632         pic16_aopPut(AOP(result),"a",0);
6633         goto release ;
6634       }
6635
6636       if (ifx) {
6637         genIfxJump (ifx,"a");
6638         goto release ;
6639       }
6640 */
6641       /* if the result is used in an arithmetic operation
6642          then put the result in place */
6643 /*
6644       if (AOP_TYPE(result) != AOP_CRY) 
6645         pic16_outAcc(result);
6646 */
6647       /* leave the result in acc */
6648     }
6649
6650 release:
6651     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6652     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6653     pic16_freeAsmop(result,NULL,ic,TRUE);
6654 }
6655 #endif
6656
6657 /*-----------------------------------------------------------------*/
6658 /* ifxForOp - returns the icode containing the ifx for operand     */
6659 /*-----------------------------------------------------------------*/
6660 static iCode *ifxForOp ( operand *op, iCode *ic )
6661 {
6662     /* if true symbol then needs to be assigned */
6663     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6664     if (IS_TRUE_SYMOP(op))
6665         return NULL ;
6666
6667     /* if this has register type condition and
6668     the next instruction is ifx with the same operand
6669     and live to of the operand is upto the ifx only then */
6670     if (ic->next
6671         && ic->next->op == IFX
6672         && IC_COND(ic->next)->key == op->key
6673         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6674         ) {
6675                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6676           return ic->next;
6677     }
6678
6679     if (ic->next &&
6680         ic->next->op == IFX &&
6681         IC_COND(ic->next)->key == op->key) {
6682       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6683       return ic->next;
6684     }
6685
6686     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6687     if (ic->next &&
6688         ic->next->op == IFX)
6689       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6690
6691     if (ic->next &&
6692         ic->next->op == IFX &&
6693         IC_COND(ic->next)->key == op->key) {
6694       DEBUGpic16_emitcode ("; "," key is okay");
6695       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6696                            OP_SYMBOL(op)->liveTo,
6697                            ic->next->seq);
6698     }
6699
6700 #if 0
6701     /* the code below is completely untested
6702      * it just allows ulong2fs.c compile -- VR */
6703          
6704     ic = ic->next;
6705     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6706                                         __FILE__, __FUNCTION__, __LINE__);
6707         
6708     /* if this has register type condition and
6709     the next instruction is ifx with the same operand
6710     and live to of the operand is upto the ifx only then */
6711     if (ic->next &&
6712         ic->next->op == IFX &&
6713         IC_COND(ic->next)->key == op->key &&
6714         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6715         return ic->next;
6716
6717     if (ic->next &&
6718         ic->next->op == IFX &&
6719         IC_COND(ic->next)->key == op->key) {
6720       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6721       return ic->next;
6722     }
6723
6724     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6725                                         __FILE__, __FUNCTION__, __LINE__);
6726
6727 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6728 #endif
6729
6730     return NULL;
6731 }
6732 /*-----------------------------------------------------------------*/
6733 /* genAndOp - for && operation                                     */
6734 /*-----------------------------------------------------------------*/
6735 static void genAndOp (iCode *ic)
6736 {
6737     operand *left,*right, *result;
6738 /*     symbol *tlbl; */
6739
6740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6741     /* note here that && operations that are in an
6742     if statement are taken away by backPatchLabels
6743     only those used in arthmetic operations remain */
6744     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6745     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6746     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6747
6748     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6749
6750     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6751     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6752     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6753
6754     /* if both are bit variables */
6755 /*     if (AOP_TYPE(left) == AOP_CRY && */
6756 /*         AOP_TYPE(right) == AOP_CRY ) { */
6757 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6758 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6759 /*         pic16_outBitC(result); */
6760 /*     } else { */
6761 /*         tlbl = newiTempLabel(NULL); */
6762 /*         pic16_toBoolean(left);     */
6763 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6764 /*         pic16_toBoolean(right); */
6765 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6766 /*         pic16_outBitAcc(result); */
6767 /*     } */
6768
6769     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6770     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771     pic16_freeAsmop(result,NULL,ic,TRUE);
6772 }
6773
6774
6775 /*-----------------------------------------------------------------*/
6776 /* genOrOp - for || operation                                      */
6777 /*-----------------------------------------------------------------*/
6778 /*
6779   tsd pic port -
6780   modified this code, but it doesn't appear to ever get called
6781 */
6782
6783 static void genOrOp (iCode *ic)
6784 {
6785     operand *left,*right, *result;
6786     symbol *tlbl;
6787
6788     /* note here that || operations that are in an
6789     if statement are taken away by backPatchLabels
6790     only those used in arthmetic operations remain */
6791     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6792     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6793     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6794     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6795
6796     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6797
6798     /* if both are bit variables */
6799     if (AOP_TYPE(left) == AOP_CRY &&
6800         AOP_TYPE(right) == AOP_CRY ) {
6801       pic16_emitcode("clrc","");
6802       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6803                AOP(left)->aopu.aop_dir,
6804                AOP(left)->aopu.aop_dir);
6805       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6806                AOP(right)->aopu.aop_dir,
6807                AOP(right)->aopu.aop_dir);
6808       pic16_emitcode("setc","");
6809
6810     } else {
6811         tlbl = newiTempLabel(NULL);
6812         pic16_toBoolean(left);
6813         emitSKPZ;
6814         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6815         pic16_toBoolean(right);
6816         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6817
6818         pic16_outBitAcc(result);
6819     }
6820
6821     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6822     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6823     pic16_freeAsmop(result,NULL,ic,TRUE);            
6824 }
6825
6826 /*-----------------------------------------------------------------*/
6827 /* isLiteralBit - test if lit == 2^n                               */
6828 /*-----------------------------------------------------------------*/
6829 static int isLiteralBit(unsigned long lit)
6830 {
6831     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6832     0x100L,0x200L,0x400L,0x800L,
6833     0x1000L,0x2000L,0x4000L,0x8000L,
6834     0x10000L,0x20000L,0x40000L,0x80000L,
6835     0x100000L,0x200000L,0x400000L,0x800000L,
6836     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6837     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6838     int idx;
6839     
6840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6841     for(idx = 0; idx < 32; idx++)
6842         if(lit == pw[idx])
6843             return idx+1;
6844     return 0;
6845 }
6846
6847 /*-----------------------------------------------------------------*/
6848 /* continueIfTrue -                                                */
6849 /*-----------------------------------------------------------------*/
6850 static void continueIfTrue (iCode *ic)
6851 {
6852     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6853     if(IC_TRUE(ic))
6854         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6855     ic->generated = 1;
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* jmpIfTrue -                                                     */
6860 /*-----------------------------------------------------------------*/
6861 static void jumpIfTrue (iCode *ic)
6862 {
6863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864     if(!IC_TRUE(ic))
6865         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6866     ic->generated = 1;
6867 }
6868
6869 /*-----------------------------------------------------------------*/
6870 /* jmpTrueOrFalse -                                                */
6871 /*-----------------------------------------------------------------*/
6872 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6873 {
6874     // ugly but optimized by peephole
6875     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6876     if(IC_TRUE(ic)){
6877         symbol *nlbl = newiTempLabel(NULL);
6878         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6879         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6880         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6881         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6882     }
6883     else{
6884         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6885         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6886     }
6887     ic->generated = 1;
6888 }
6889
6890 /*-----------------------------------------------------------------*/
6891 /* genAnd  - code for and                                          */
6892 /*-----------------------------------------------------------------*/
6893 static void genAnd (iCode *ic, iCode *ifx)
6894 {
6895   operand *left, *right, *result;
6896   int size, offset=0;  
6897   unsigned long lit = 0L;
6898   int bytelit = 0;
6899   resolvedIfx rIfx;
6900
6901
6902   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6903   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6904   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6905   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6906
6907   resolveIfx(&rIfx,ifx);
6908
6909   /* if left is a literal & right is not then exchange them */
6910   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6911       AOP_NEEDSACC(left)) {
6912     operand *tmp = right ;
6913     right = left;
6914     left = tmp;
6915   }
6916
6917   /* if result = right then exchange them */
6918   if(pic16_sameRegs(AOP(result),AOP(right))){
6919     operand *tmp = right ;
6920     right = left;
6921     left = tmp;
6922   }
6923
6924   /* if right is bit then exchange them */
6925   if (AOP_TYPE(right) == AOP_CRY &&
6926       AOP_TYPE(left) != AOP_CRY){
6927     operand *tmp = right ;
6928     right = left;
6929     left = tmp;
6930   }
6931   if(AOP_TYPE(right) == AOP_LIT)
6932     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6933
6934   size = AOP_SIZE(result);
6935
6936   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6937
6938   // if(bit & yy)
6939   // result = bit & yy;
6940   if (AOP_TYPE(left) == AOP_CRY){
6941     // c = bit & literal;
6942     if(AOP_TYPE(right) == AOP_LIT){
6943       if(lit & 1) {
6944         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6945           // no change
6946           goto release;
6947         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6948       } else {
6949         // bit(result) = 0;
6950         if(size && (AOP_TYPE(result) == AOP_CRY)){
6951           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6952           goto release;
6953         }
6954         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6955           jumpIfTrue(ifx);
6956           goto release;
6957         }
6958         pic16_emitcode("clr","c");
6959       }
6960     } else {
6961       if (AOP_TYPE(right) == AOP_CRY){
6962         // c = bit & bit;
6963         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6964         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6965       } else {
6966         // c = bit & val;
6967         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6968         // c = lsb
6969         pic16_emitcode("rrc","a");
6970         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6971       }
6972     }
6973     // bit = c
6974     // val = c
6975     if(size)
6976       pic16_outBitC(result);
6977     // if(bit & ...)
6978     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6979       genIfxJump(ifx, "c");           
6980     goto release ;
6981   }
6982
6983   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6984   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6985   if((AOP_TYPE(right) == AOP_LIT) &&
6986      (AOP_TYPE(result) == AOP_CRY) &&
6987      (AOP_TYPE(left) != AOP_CRY)){
6988     int posbit = isLiteralBit(lit);
6989     /* left &  2^n */
6990     if(posbit){
6991       posbit--;
6992       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6993       // bit = left & 2^n
6994       if(size)
6995         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6996       // if(left &  2^n)
6997       else{
6998         if(ifx){
6999 /*
7000           if(IC_TRUE(ifx)) {
7001             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7002             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7003           } else {
7004             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7005             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7006           }
7007 */
7008         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7009         size = AOP_SIZE(left);
7010
7011         {
7012           int bp = posbit, ofs=0;
7013           
7014             while(bp > 7) {
7015               bp -= 8;
7016               ofs++;
7017             }
7018         
7019           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7020                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7021
7022         }
7023 /*
7024           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7025                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7026 */
7027           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7028           
7029           ifx->generated = 1;
7030         }
7031         goto release;
7032       }
7033     } else {
7034       symbol *tlbl = newiTempLabel(NULL);
7035       int sizel = AOP_SIZE(left);
7036
7037       if(size)
7038         emitSETC;
7039
7040       while(sizel--) {
7041         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7042
7043           /* patch provided by Aaron Colwell */
7044           if((posbit = isLiteralBit(bytelit)) != 0) {
7045               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7046                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7047                                                 (posbit-1),0, PO_GPR_REGISTER));
7048
7049               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7050 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7051           } else {
7052               if (bytelit == 0xff) {
7053                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7054                    * a peephole could optimize it out -- VR */
7055                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7056               } else {
7057                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7058                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7059               }
7060
7061               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7062                             pic16_popGetLabel(tlbl->key));
7063           }
7064         
7065 #if 0
7066           /* old code, left here for reference -- VR 09/2004 */
7067           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7068           // byte ==  2^n ?
7069           if((posbit = isLiteralBit(bytelit)) != 0)
7070             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7071           else{
7072             if(bytelit != 0x0FFL)
7073               pic16_emitcode("anl","a,%s",
7074                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7075             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7076           }
7077 #endif
7078         }
7079         offset++;
7080       }
7081       // bit = left & literal
7082       if(size) {
7083         emitCLRC;
7084         pic16_emitpLabel(tlbl->key);
7085       }
7086       // if(left & literal)
7087       else {
7088         if(ifx) {
7089           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7090           pic16_emitpLabel(tlbl->key);
7091           ifx->generated = 1;
7092         }
7093         goto release;
7094       }
7095     }
7096
7097     pic16_outBitC(result);
7098     goto release ;
7099   }
7100
7101   /* if left is same as result */
7102   if(pic16_sameRegs(AOP(result),AOP(left))){
7103     int know_W = -1;
7104     for(;size--; offset++,lit>>=8) {
7105       if(AOP_TYPE(right) == AOP_LIT){
7106         switch(lit & 0xff) {
7107         case 0x00:
7108           /*  and'ing with 0 has clears the result */
7109 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7110           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7111           break;
7112         case 0xff:
7113           /* and'ing with 0xff is a nop when the result and left are the same */
7114           break;
7115
7116         default:
7117           {
7118             int p = my_powof2( (~lit) & 0xff );
7119             if(p>=0) {
7120               /* only one bit is set in the literal, so use a bcf instruction */
7121 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7122               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7123
7124             } else {
7125               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7126               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7127               if(know_W != (lit&0xff))
7128                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7129               know_W = lit &0xff;
7130               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7131             }
7132           }    
7133         }
7134       } else {
7135         if (AOP_TYPE(left) == AOP_ACC) {
7136           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7137         } else {                    
7138           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7139           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7140
7141         }
7142       }
7143     }
7144
7145   } else {
7146     // left & result in different registers
7147     if(AOP_TYPE(result) == AOP_CRY){
7148       // result = bit
7149       // if(size), result in bit
7150       // if(!size && ifx), conditional oper: if(left & right)
7151       symbol *tlbl = newiTempLabel(NULL);
7152       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7153       if(size)
7154         pic16_emitcode("setb","c");
7155       while(sizer--){
7156         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7157         pic16_emitcode("anl","a,%s",
7158                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7159         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7160         offset++;
7161       }
7162       if(size){
7163         CLRC;
7164         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7165         pic16_outBitC(result);
7166       } else if(ifx)
7167         jmpTrueOrFalse(ifx, tlbl);
7168     } else {
7169       for(;(size--);offset++) {
7170         // normal case
7171         // result = left & right
7172         if(AOP_TYPE(right) == AOP_LIT){
7173           int t = (lit >> (offset*8)) & 0x0FFL;
7174           switch(t) { 
7175           case 0x00:
7176             pic16_emitcode("clrf","%s",
7177                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7178             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7179             break;
7180           case 0xff:
7181             pic16_emitcode("movf","%s,w",
7182                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7183             pic16_emitcode("movwf","%s",
7184                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7185             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7186             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7187             break;
7188           default:
7189             pic16_emitcode("movlw","0x%x",t);
7190             pic16_emitcode("andwf","%s,w",
7191                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7192             pic16_emitcode("movwf","%s",
7193                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7194               
7195             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7196             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7197             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7198           }
7199           continue;
7200         }
7201
7202         if (AOP_TYPE(left) == AOP_ACC) {
7203           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7204           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7205         } else {
7206           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7207           pic16_emitcode("andwf","%s,w",
7208                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7209           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7210           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7211         }
7212         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7213         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7214       }
7215     }
7216   }
7217
7218   release :
7219     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7220   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221   pic16_freeAsmop(result,NULL,ic,TRUE);     
7222 }
7223
7224 /*-----------------------------------------------------------------*/
7225 /* genOr  - code for or                                            */
7226 /*-----------------------------------------------------------------*/
7227 static void genOr (iCode *ic, iCode *ifx)
7228 {
7229     operand *left, *right, *result;
7230     int size, offset=0;
7231     unsigned long lit = 0L;
7232
7233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7234
7235     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7236     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7237     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7238
7239     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7240
7241     /* if left is a literal & right is not then exchange them */
7242     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7243         AOP_NEEDSACC(left)) {
7244         operand *tmp = right ;
7245         right = left;
7246         left = tmp;
7247     }
7248
7249     /* if result = right then exchange them */
7250     if(pic16_sameRegs(AOP(result),AOP(right))){
7251         operand *tmp = right ;
7252         right = left;
7253         left = tmp;
7254     }
7255
7256     /* if right is bit then exchange them */
7257     if (AOP_TYPE(right) == AOP_CRY &&
7258         AOP_TYPE(left) != AOP_CRY){
7259         operand *tmp = right ;
7260         right = left;
7261         left = tmp;
7262     }
7263
7264     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7265
7266     if(AOP_TYPE(right) == AOP_LIT)
7267         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7268
7269     size = AOP_SIZE(result);
7270
7271     // if(bit | yy)
7272     // xx = bit | yy;
7273     if (AOP_TYPE(left) == AOP_CRY){
7274         if(AOP_TYPE(right) == AOP_LIT){
7275             // c = bit & literal;
7276             if(lit){
7277                 // lit != 0 => result = 1
7278                 if(AOP_TYPE(result) == AOP_CRY){
7279                   if(size)
7280                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7281                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7282                   //     AOP(result)->aopu.aop_dir,
7283                   //     AOP(result)->aopu.aop_dir);
7284                     else if(ifx)
7285                         continueIfTrue(ifx);
7286                     goto release;
7287                 }
7288             } else {
7289                 // lit == 0 => result = left
7290                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7291                     goto release;
7292                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7293             }
7294         } else {
7295             if (AOP_TYPE(right) == AOP_CRY){
7296               if(pic16_sameRegs(AOP(result),AOP(left))){
7297                 // c = bit | bit;
7298                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7299                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7300                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7301
7302                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7303                          AOP(result)->aopu.aop_dir,
7304                          AOP(result)->aopu.aop_dir);
7305                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7306                          AOP(right)->aopu.aop_dir,
7307                          AOP(right)->aopu.aop_dir);
7308                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7309                          AOP(result)->aopu.aop_dir,
7310                          AOP(result)->aopu.aop_dir);
7311               } else {
7312                 if( AOP_TYPE(result) == AOP_ACC) {
7313                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7314                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7315                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7316                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7317
7318                 } else {
7319
7320                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7321                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7322                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7323                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7324
7325                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7326                                  AOP(result)->aopu.aop_dir,
7327                                  AOP(result)->aopu.aop_dir);
7328                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7329                                  AOP(right)->aopu.aop_dir,
7330                                  AOP(right)->aopu.aop_dir);
7331                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7332                                  AOP(left)->aopu.aop_dir,
7333                                  AOP(left)->aopu.aop_dir);
7334                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7335                                  AOP(result)->aopu.aop_dir,
7336                                  AOP(result)->aopu.aop_dir);
7337                 }
7338               }
7339             } else {
7340                 // c = bit | val;
7341                 symbol *tlbl = newiTempLabel(NULL);
7342                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7343
7344
7345                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7346                 if( AOP_TYPE(right) == AOP_ACC) {
7347                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7348                   emitSKPNZ;
7349                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7350                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7351                 }
7352
7353
7354
7355                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7356                     pic16_emitcode(";XXX setb","c");
7357                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7358                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7359                 pic16_toBoolean(right);
7360                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7361                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7362                     jmpTrueOrFalse(ifx, tlbl);
7363                     goto release;
7364                 } else {
7365                     CLRC;
7366                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7367                 }
7368             }
7369         }
7370         // bit = c
7371         // val = c
7372         if(size)
7373             pic16_outBitC(result);
7374         // if(bit | ...)
7375         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7376             genIfxJump(ifx, "c");           
7377         goto release ;
7378     }
7379
7380     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7381     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7382     if((AOP_TYPE(right) == AOP_LIT) &&
7383        (AOP_TYPE(result) == AOP_CRY) &&
7384        (AOP_TYPE(left) != AOP_CRY)){
7385         if(lit){
7386           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7387             // result = 1
7388             if(size)
7389                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7390             else 
7391                 continueIfTrue(ifx);
7392             goto release;
7393         } else {
7394           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7395             // lit = 0, result = boolean(left)
7396             if(size)
7397                 pic16_emitcode(";XXX setb","c");
7398             pic16_toBoolean(right);
7399             if(size){
7400                 symbol *tlbl = newiTempLabel(NULL);
7401                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7402                 CLRC;
7403                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7404             } else {
7405                 genIfxJump (ifx,"a");
7406                 goto release;
7407             }
7408         }
7409         pic16_outBitC(result);
7410         goto release ;
7411     }
7412
7413     /* if left is same as result */
7414     if(pic16_sameRegs(AOP(result),AOP(left))){
7415       int know_W = -1;
7416       for(;size--; offset++,lit>>=8) {
7417         if(AOP_TYPE(right) == AOP_LIT){
7418           if((lit & 0xff) == 0)
7419             /*  or'ing with 0 has no effect */
7420             continue;
7421           else {
7422             int p = my_powof2(lit & 0xff);
7423             if(p>=0) {
7424               /* only one bit is set in the literal, so use a bsf instruction */
7425               pic16_emitpcode(POC_BSF,
7426                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7427             } else {
7428               if(know_W != (lit & 0xff))
7429                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7430               know_W = lit & 0xff;
7431               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7432             }
7433                     
7434           }
7435         } else {
7436           if (AOP_TYPE(left) == AOP_ACC) {
7437             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7438             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7439           } else {                  
7440             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7441             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7442
7443             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7444             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7445
7446           }
7447         }
7448       }
7449     } else {
7450         // left & result in different registers
7451         if(AOP_TYPE(result) == AOP_CRY){
7452             // result = bit
7453             // if(size), result in bit
7454             // if(!size && ifx), conditional oper: if(left | right)
7455             symbol *tlbl = newiTempLabel(NULL);
7456             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7457             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7458
7459
7460             if(size)
7461                 pic16_emitcode(";XXX setb","c");
7462             while(sizer--){
7463                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7464                 pic16_emitcode(";XXX orl","a,%s",
7465                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7466                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7467                 offset++;
7468             }
7469             if(size){
7470                 CLRC;
7471                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7472                 pic16_outBitC(result);
7473             } else if(ifx)
7474                 jmpTrueOrFalse(ifx, tlbl);
7475         } else for(;(size--);offset++){
7476           // normal case
7477           // result = left & right
7478           if(AOP_TYPE(right) == AOP_LIT){
7479             int t = (lit >> (offset*8)) & 0x0FFL;
7480             switch(t) { 
7481             case 0x00:
7482               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7483               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7484
7485               pic16_emitcode("movf","%s,w",
7486                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7487               pic16_emitcode("movwf","%s",
7488                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7489               break;
7490             default:
7491               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7492               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7493               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7494
7495               pic16_emitcode("movlw","0x%x",t);
7496               pic16_emitcode("iorwf","%s,w",
7497                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7498               pic16_emitcode("movwf","%s",
7499                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7500               
7501             }
7502             continue;
7503           }
7504
7505           // faster than result <- left, anl result,right
7506           // and better if result is SFR
7507           if (AOP_TYPE(left) == AOP_ACC) {
7508             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7509             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7510           } else {
7511             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7512             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7513
7514             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7515             pic16_emitcode("iorwf","%s,w",
7516                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7517           }
7518           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7519           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7520         }
7521     }
7522
7523 release :
7524     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7525     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7526     pic16_freeAsmop(result,NULL,ic,TRUE);     
7527 }
7528
7529 /*-----------------------------------------------------------------*/
7530 /* genXor - code for xclusive or                                   */
7531 /*-----------------------------------------------------------------*/
7532 static void genXor (iCode *ic, iCode *ifx)
7533 {
7534   operand *left, *right, *result;
7535   int size, offset=0;
7536   unsigned long lit = 0L;
7537
7538   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7539
7540   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7541   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7542   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7543
7544   /* if left is a literal & right is not ||
7545      if left needs acc & right does not */
7546   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7547       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7548     operand *tmp = right ;
7549     right = left;
7550     left = tmp;
7551   }
7552
7553   /* if result = right then exchange them */
7554   if(pic16_sameRegs(AOP(result),AOP(right))){
7555     operand *tmp = right ;
7556     right = left;
7557     left = tmp;
7558   }
7559
7560   /* if right is bit then exchange them */
7561   if (AOP_TYPE(right) == AOP_CRY &&
7562       AOP_TYPE(left) != AOP_CRY){
7563     operand *tmp = right ;
7564     right = left;
7565     left = tmp;
7566   }
7567   if(AOP_TYPE(right) == AOP_LIT)
7568     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7569
7570   size = AOP_SIZE(result);
7571
7572   // if(bit ^ yy)
7573   // xx = bit ^ yy;
7574   if (AOP_TYPE(left) == AOP_CRY){
7575     if(AOP_TYPE(right) == AOP_LIT){
7576       // c = bit & literal;
7577       if(lit>>1){
7578         // lit>>1  != 0 => result = 1
7579         if(AOP_TYPE(result) == AOP_CRY){
7580           if(size)
7581             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7582             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7583           else if(ifx)
7584             continueIfTrue(ifx);
7585           goto release;
7586         }
7587         pic16_emitcode("setb","c");
7588       } else{
7589         // lit == (0 or 1)
7590         if(lit == 0){
7591           // lit == 0, result = left
7592           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7593             goto release;
7594           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7595         } else{
7596           // lit == 1, result = not(left)
7597           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7598             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7599             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7600             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7601             goto release;
7602           } else {
7603             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7604             pic16_emitcode("cpl","c");
7605           }
7606         }
7607       }
7608
7609     } else {
7610       // right != literal
7611       symbol *tlbl = newiTempLabel(NULL);
7612       if (AOP_TYPE(right) == AOP_CRY){
7613         // c = bit ^ bit;
7614         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7615       }
7616       else{
7617         int sizer = AOP_SIZE(right);
7618         // c = bit ^ val
7619         // if val>>1 != 0, result = 1
7620         pic16_emitcode("setb","c");
7621         while(sizer){
7622           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7623           if(sizer == 1)
7624             // test the msb of the lsb
7625             pic16_emitcode("anl","a,#0xfe");
7626           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7627           sizer--;
7628         }
7629         // val = (0,1)
7630         pic16_emitcode("rrc","a");
7631       }
7632       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7633       pic16_emitcode("cpl","c");
7634       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7635     }
7636     // bit = c
7637     // val = c
7638     if(size)
7639       pic16_outBitC(result);
7640     // if(bit | ...)
7641     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7642       genIfxJump(ifx, "c");           
7643     goto release ;
7644   }
7645
7646   if(pic16_sameRegs(AOP(result),AOP(left))){
7647     /* if left is same as result */
7648     for(;size--; offset++) {
7649       if(AOP_TYPE(right) == AOP_LIT){
7650         int t  = (lit >> (offset*8)) & 0x0FFL;
7651         if(t == 0x00L)
7652           continue;
7653         else
7654           if (IS_AOP_PREG(left)) {
7655             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7656             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7657             pic16_aopPut(AOP(result),"a",offset);
7658           } else {
7659             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7660             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7661             pic16_emitcode("xrl","%s,%s",
7662                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7663                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7664           }
7665       } else {
7666         if (AOP_TYPE(left) == AOP_ACC)
7667           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7668         else {
7669           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7670           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7671 /*
7672           if (IS_AOP_PREG(left)) {
7673             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7674             pic16_aopPut(AOP(result),"a",offset);
7675           } else
7676             pic16_emitcode("xrl","%s,a",
7677                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7678 */
7679         }
7680       }
7681     }
7682   } else {
7683     // left & result in different registers
7684     if(AOP_TYPE(result) == AOP_CRY){
7685       // result = bit
7686       // if(size), result in bit
7687       // if(!size && ifx), conditional oper: if(left ^ right)
7688       symbol *tlbl = newiTempLabel(NULL);
7689       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7690       if(size)
7691         pic16_emitcode("setb","c");
7692       while(sizer--){
7693         if((AOP_TYPE(right) == AOP_LIT) &&
7694            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7695           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7696         } else {
7697           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7698           pic16_emitcode("xrl","a,%s",
7699                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7700         }
7701         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7702         offset++;
7703       }
7704       if(size){
7705         CLRC;
7706         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7707         pic16_outBitC(result);
7708       } else if(ifx)
7709         jmpTrueOrFalse(ifx, tlbl);
7710     } else for(;(size--);offset++){
7711       // normal case
7712       // result = left & right
7713       if(AOP_TYPE(right) == AOP_LIT){
7714         int t = (lit >> (offset*8)) & 0x0FFL;
7715         switch(t) { 
7716         case 0x00:
7717           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7718           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7719           pic16_emitcode("movf","%s,w",
7720                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7721           pic16_emitcode("movwf","%s",
7722                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7723           break;
7724         case 0xff:
7725           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7726           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7727           pic16_emitcode("comf","%s,w",
7728                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7729           pic16_emitcode("movwf","%s",
7730                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7731           break;
7732         default:
7733           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7734           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7735           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7736           pic16_emitcode("movlw","0x%x",t);
7737           pic16_emitcode("xorwf","%s,w",
7738                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7739           pic16_emitcode("movwf","%s",
7740                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7741
7742         }
7743         continue;
7744       }
7745
7746       // faster than result <- left, anl result,right
7747       // and better if result is SFR
7748       if (AOP_TYPE(left) == AOP_ACC) {
7749         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7750         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7751       } else {
7752         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7753         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7754         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7755         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7756       }
7757       if ( AOP_TYPE(result) != AOP_ACC){
7758         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7759         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7760       }
7761     }
7762   }
7763
7764   release :
7765     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7766   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7767   pic16_freeAsmop(result,NULL,ic,TRUE);     
7768 }
7769
7770 /*-----------------------------------------------------------------*/
7771 /* genInline - write the inline code out                           */
7772 /*-----------------------------------------------------------------*/
7773 static void genInline (iCode *ic)
7774 {
7775   char *buffer, *bp, *bp1;
7776     
7777         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7778
7779         _G.inLine += (!options.asmpeep);
7780
7781         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7782         strcpy(buffer,IC_INLINE(ic));
7783
7784 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7785
7786         /* emit each line as a code */
7787         while (*bp) {
7788                 if (*bp == '\n') {
7789                         *bp++ = '\0';
7790
7791                         if(*bp1)
7792                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7793                         bp1 = bp;
7794                 } else {
7795                         if (*bp == ':') {
7796                                 bp++;
7797                                 *bp = '\0';
7798                                 bp++;
7799
7800                                 /* print label, use this special format with NULL directive
7801                                  * to denote that the argument should not be indented with tab */
7802                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7803                                 bp1 = bp;
7804                         } else
7805                                 bp++;
7806                 }
7807         }
7808
7809         if ((bp1 != bp) && *bp1)
7810                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7811
7812
7813     Safe_free(buffer);
7814
7815     _G.inLine -= (!options.asmpeep);
7816 }
7817
7818 /*-----------------------------------------------------------------*/
7819 /* genRRC - rotate right with carry                                */
7820 /*-----------------------------------------------------------------*/
7821 static void genRRC (iCode *ic)
7822 {
7823   operand *left , *result ;
7824   int size, offset = 0, same;
7825
7826   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7827
7828   /* rotate right with carry */
7829   left = IC_LEFT(ic);
7830   result=IC_RESULT(ic);
7831   pic16_aopOp (left,ic,FALSE);
7832   pic16_aopOp (result,ic,FALSE);
7833
7834   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7835
7836   same = pic16_sameRegs(AOP(result),AOP(left));
7837
7838   size = AOP_SIZE(result);    
7839
7840   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7841
7842   /* get the lsb and put it into the carry */
7843   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7844
7845   offset = 0 ;
7846
7847   while(size--) {
7848
7849     if(same) {
7850       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7851     } else {
7852       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7853       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7854     }
7855
7856     offset++;
7857   }
7858
7859   pic16_freeAsmop(left,NULL,ic,TRUE);
7860   pic16_freeAsmop(result,NULL,ic,TRUE);
7861 }
7862
7863 /*-----------------------------------------------------------------*/
7864 /* genRLC - generate code for rotate left with carry               */
7865 /*-----------------------------------------------------------------*/
7866 static void genRLC (iCode *ic)
7867 {    
7868   operand *left , *result ;
7869   int size, offset = 0;
7870   int same;
7871
7872   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7873   /* rotate right with carry */
7874   left = IC_LEFT(ic);
7875   result=IC_RESULT(ic);
7876   pic16_aopOp (left,ic,FALSE);
7877   pic16_aopOp (result,ic,FALSE);
7878
7879   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7880
7881   same = pic16_sameRegs(AOP(result),AOP(left));
7882
7883   /* move it to the result */
7884   size = AOP_SIZE(result);    
7885
7886   /* get the msb and put it into the carry */
7887   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7888
7889   offset = 0 ;
7890
7891   while(size--) {
7892
7893     if(same) {
7894       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7895     } else {
7896       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7898     }
7899
7900     offset++;
7901   }
7902
7903
7904   pic16_freeAsmop(left,NULL,ic,TRUE);
7905   pic16_freeAsmop(result,NULL,ic,TRUE);
7906 }
7907
7908
7909 /* gpasm can get the highest order bit with HIGH/UPPER
7910  * so the following probably is not needed -- VR */
7911  
7912 /*-----------------------------------------------------------------*/
7913 /* genGetHbit - generates code get highest order bit               */
7914 /*-----------------------------------------------------------------*/
7915 static void genGetHbit (iCode *ic)
7916 {
7917     operand *left, *result;
7918     left = IC_LEFT(ic);
7919     result=IC_RESULT(ic);
7920     pic16_aopOp (left,ic,FALSE);
7921     pic16_aopOp (result,ic,FALSE);
7922
7923     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7924     /* get the highest order byte into a */
7925     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7926     if(AOP_TYPE(result) == AOP_CRY){
7927         pic16_emitcode("rlc","a");
7928         pic16_outBitC(result);
7929     }
7930     else{
7931         pic16_emitcode("rl","a");
7932         pic16_emitcode("anl","a,#0x01");
7933         pic16_outAcc(result);
7934     }
7935
7936
7937     pic16_freeAsmop(left,NULL,ic,TRUE);
7938     pic16_freeAsmop(result,NULL,ic,TRUE);
7939 }
7940
7941 #if 0
7942 /*-----------------------------------------------------------------*/
7943 /* AccRol - rotate left accumulator by known count                 */
7944 /*-----------------------------------------------------------------*/
7945 static void AccRol (int shCount)
7946 {
7947     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7948     shCount &= 0x0007;              // shCount : 0..7
7949     switch(shCount){
7950         case 0 :
7951             break;
7952         case 1 :
7953             pic16_emitcode("rl","a");
7954             break;
7955         case 2 :
7956             pic16_emitcode("rl","a");
7957             pic16_emitcode("rl","a");
7958             break;
7959         case 3 :
7960             pic16_emitcode("swap","a");
7961             pic16_emitcode("rr","a");
7962             break;
7963         case 4 :
7964             pic16_emitcode("swap","a");
7965             break;
7966         case 5 :
7967             pic16_emitcode("swap","a");
7968             pic16_emitcode("rl","a");
7969             break;
7970         case 6 :
7971             pic16_emitcode("rr","a");
7972             pic16_emitcode("rr","a");
7973             break;
7974         case 7 :
7975             pic16_emitcode("rr","a");
7976             break;
7977     }
7978 }
7979 #endif
7980
7981 /*-----------------------------------------------------------------*/
7982 /* AccLsh - left shift accumulator by known count                  */
7983 /*-----------------------------------------------------------------*/
7984 static void AccLsh (int shCount)
7985 {
7986         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7987         switch(shCount){
7988                 case 0 :
7989                         return;
7990                         break;
7991                 case 1 :
7992                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7993                         break;
7994                 case 2 :
7995                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7996                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7997                         break;
7998                 case 3 :
7999                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8000                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8001                         break;
8002                 case 4 :
8003                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8004                         break;
8005                 case 5 :
8006                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8007                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8008                         break;
8009                 case 6 :
8010                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8011                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8012                         break;
8013                 case 7 :
8014                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8015                         break;
8016         }
8017
8018         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8019 }
8020
8021 /*-----------------------------------------------------------------*/
8022 /* AccRsh - right shift accumulator by known count                 */
8023 /*-----------------------------------------------------------------*/
8024 static void AccRsh (int shCount, int andmask)
8025 {
8026         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8027         switch(shCount){
8028                 case 0 :
8029                         return; break;
8030                 case 1 :
8031                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8032                         break;
8033                 case 2 :
8034                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8035                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8036                         break;
8037                 case 3 :
8038                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8039                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8040                         break;
8041                 case 4 :
8042                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8043                         break;
8044                 case 5 :
8045                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8046                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8047                         break;
8048                 case 6 :
8049                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8050                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8051                         break;
8052                 case 7 :
8053                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8054                         break;
8055         }
8056         
8057         if(andmask)
8058                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8059         else
8060                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8061 }
8062
8063 #if 0
8064 /*-----------------------------------------------------------------*/
8065 /* AccSRsh - signed right shift accumulator by known count                 */
8066 /*-----------------------------------------------------------------*/
8067 static void AccSRsh (int shCount)
8068 {
8069     symbol *tlbl ;
8070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8071     if(shCount != 0){
8072         if(shCount == 1){
8073             pic16_emitcode("mov","c,acc.7");
8074             pic16_emitcode("rrc","a");
8075         } else if(shCount == 2){
8076             pic16_emitcode("mov","c,acc.7");
8077             pic16_emitcode("rrc","a");
8078             pic16_emitcode("mov","c,acc.7");
8079             pic16_emitcode("rrc","a");
8080         } else {
8081             tlbl = newiTempLabel(NULL);
8082             /* rotate right accumulator */
8083             AccRol(8 - shCount);
8084             /* and kill the higher order bits */
8085             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8086             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8087             pic16_emitcode("orl","a,#0x%02x",
8088                      (unsigned char)~SRMask[shCount]);
8089             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8090         }
8091     }
8092 }
8093 #endif
8094
8095 /*-----------------------------------------------------------------*/
8096 /* shiftR1Left2Result - shift right one byte from left to result   */
8097 /*-----------------------------------------------------------------*/
8098 static void shiftR1Left2ResultSigned (operand *left, int offl,
8099                                 operand *result, int offr,
8100                                 int shCount)
8101 {
8102   int same;
8103
8104   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8105
8106   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8107
8108   switch(shCount) {
8109   case 1:
8110     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8111     if(same) 
8112       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8113     else {
8114       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8115       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8116     }
8117
8118     break;
8119   case 2:
8120
8121     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8122     if(same) 
8123       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8124     else {
8125       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8126       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8127     }
8128     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8129     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8130
8131     break;
8132
8133   case 3:
8134     if(same)
8135       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8136     else {
8137       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8138       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8139     }
8140
8141     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8142     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8143     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8144
8145     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8146     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8147
8148     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8149     break;
8150
8151   case 4:
8152     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8153     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8154     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8155     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8156     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8157     break;
8158   case 5:
8159     if(same) {
8160       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8161     } else {
8162       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8163       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8164     }
8165     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8166     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8167     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8168     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8169     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8170     break;
8171
8172   case 6:
8173     if(same) {
8174       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8175       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8176       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8177       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8178       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8179       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8180     } else {
8181       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8182       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8183       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8184       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8185       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8186     }
8187     break;
8188
8189   case 7:
8190     if(same) {
8191       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8192       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8193       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8194       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8195     } else {
8196       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8197       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8198       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8199     }
8200
8201   default:
8202     break;
8203   }
8204 }
8205
8206 /*-----------------------------------------------------------------*/
8207 /* shiftR1Left2Result - shift right one byte from left to result   */
8208 /*-----------------------------------------------------------------*/
8209 static void shiftR1Left2Result (operand *left, int offl,
8210                                 operand *result, int offr,
8211                                 int shCount, int sign)
8212 {
8213   int same;
8214
8215   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8216
8217   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8218
8219   /* Copy the msb into the carry if signed. */
8220   if(sign) {
8221     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8222     return;
8223   }
8224
8225
8226
8227   switch(shCount) {
8228   case 1:
8229     emitCLRC;
8230     if(same) 
8231       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8232     else {
8233       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8234       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8235     }
8236     break;
8237   case 2:
8238     emitCLRC;
8239     if(same) {
8240       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8241     } else {
8242       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8243       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8244     }
8245     emitCLRC;
8246     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8247
8248     break;
8249   case 3:
8250     if(same)
8251       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8252     else {
8253       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8254       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8255     }
8256
8257     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8258     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8259     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8260     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8261     break;
8262       
8263   case 4:
8264     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8265     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8266     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8267     break;
8268
8269   case 5:
8270     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8271     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8272     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8273     //emitCLRC;
8274     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8275
8276     break;
8277   case 6:
8278
8279     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8280     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8281     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8282     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8283     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8284     break;
8285
8286   case 7:
8287
8288     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8289     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8290     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8291
8292     break;
8293
8294   default:
8295     break;
8296   }
8297 }
8298
8299 /*-----------------------------------------------------------------*/
8300 /* shiftL1Left2Result - shift left one byte from left to result    */
8301 /*-----------------------------------------------------------------*/
8302 static void shiftL1Left2Result (operand *left, int offl,
8303                                 operand *result, int offr, int shCount)
8304 {
8305   int same;
8306
8307   //    char *l;
8308   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8309
8310   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8311   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8312     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8313     //    MOVA(l);
8314     /* shift left accumulator */
8315     //AccLsh(shCount); // don't comment out just yet...
8316   //    pic16_aopPut(AOP(result),"a",offr);
8317
8318   switch(shCount) {
8319   case 1:
8320     /* Shift left 1 bit position */
8321     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8322     if(same) {
8323       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8324     } else {
8325       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8326       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8327     }
8328     break;
8329   case 2:
8330     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8331     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8332     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8333     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8334     break;
8335   case 3:
8336     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8337     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8338     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8339     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8340     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8341     break;
8342   case 4:
8343     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8344     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8345     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8346     break;
8347   case 5:
8348     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8349     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8350     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8351     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8352     break;
8353   case 6:
8354     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8355     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8356     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8357     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8358     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8359     break;
8360   case 7:
8361     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8362     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8363     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8364     break;
8365
8366   default:
8367     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8368   }
8369
8370 }
8371
8372 /*-----------------------------------------------------------------*/
8373 /* movLeft2Result - move byte from left to result                  */
8374 /*-----------------------------------------------------------------*/
8375 static void movLeft2Result (operand *left, int offl,
8376                             operand *result, int offr)
8377 {
8378   char *l;
8379   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8380   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8381     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8382
8383     if (*l == '@' && (IS_AOP_PREG(result))) {
8384       pic16_emitcode("mov","a,%s",l);
8385       pic16_aopPut(AOP(result),"a",offr);
8386     } else {
8387       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8388       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8389     }
8390   }
8391 }
8392
8393 /*-----------------------------------------------------------------*/
8394 /* shiftL2Left2Result - shift left two bytes from left to result   */
8395 /*-----------------------------------------------------------------*/
8396 static void shiftL2Left2Result (operand *left, int offl,
8397                                 operand *result, int offr, int shCount)
8398 {
8399   int same = pic16_sameRegs(AOP(result), AOP(left));
8400   int i;
8401
8402   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8403
8404   if (same && (offl != offr)) { // shift bytes
8405     if (offr > offl) {
8406        for(i=1;i>-1;i--) {
8407          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8408          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8409        }
8410     } else { // just treat as different later on
8411                 same = 0;
8412     }
8413   }
8414
8415   if(same) {
8416     switch(shCount) {
8417     case 0:
8418       break;
8419     case 1:
8420     case 2:
8421     case 3:
8422
8423       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8424       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8425       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8426
8427       while(--shCount) {
8428                 emitCLRC;
8429                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8430                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8431       }
8432
8433       break;
8434     case 4:
8435     case 5:
8436       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8437       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8438       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8439       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8440       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8441       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8442       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8443       if(shCount >=5) {
8444                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8445                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8446       }
8447       break;
8448     case 6:
8449       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8450       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8451       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8452       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8453       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8454       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8455       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8456       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8457       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8458       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8459       break;
8460     case 7:
8461       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8462       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8463       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8464       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8465       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8466     }
8467
8468   } else {
8469     switch(shCount) {
8470     case 0:
8471       break;
8472     case 1:
8473     case 2:
8474     case 3:
8475       /* note, use a mov/add for the shift since the mov has a
8476          chance of getting optimized out */
8477       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8478       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8479       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8480       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8481       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8482
8483       while(--shCount) {
8484                 emitCLRC;
8485                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8486                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8487       }
8488       break;
8489
8490     case 4:
8491     case 5:
8492       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8493       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8494       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8495       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8496       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8497       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8498       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8499       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8500
8501
8502       if(shCount == 5) {
8503                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8504                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8505       }
8506       break;
8507     case 6:
8508       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8509       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8510       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8511       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8512
8513       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8514       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8515       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8516       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8517       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8518       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8519       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8520       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8521       break;
8522     case 7:
8523       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8524       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8525       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8526       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8527       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8528     }
8529   }
8530
8531 }
8532 /*-----------------------------------------------------------------*/
8533 /* shiftR2Left2Result - shift right two bytes from left to result  */
8534 /*-----------------------------------------------------------------*/
8535 static void shiftR2Left2Result (operand *left, int offl,
8536                                 operand *result, int offr,
8537                                 int shCount, int sign)
8538 {
8539   int same = pic16_sameRegs(AOP(result), AOP(left));
8540   int i;
8541   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8542
8543   if (same && (offl != offr)) { // shift right bytes
8544     if (offr < offl) {
8545        for(i=0;i<2;i++) {
8546          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8547          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8548        }
8549     } else { // just treat as different later on
8550                 same = 0;
8551     }
8552   }
8553
8554   switch(shCount) {
8555   case 0:
8556     break;
8557   case 1:
8558   case 2:
8559   case 3:
8560     if(sign)
8561       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8562     else
8563       emitCLRC;
8564
8565     if(same) {
8566       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8567       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8568     } else {
8569       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8570       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8571       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8572       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8573     }
8574
8575     while(--shCount) {
8576       if(sign)
8577                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8578       else
8579                 emitCLRC;
8580       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8581       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8582     }
8583     break;
8584   case 4:
8585   case 5:
8586     if(same) {
8587
8588       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8589       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8590       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8591
8592       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8593       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8594       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8595       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8596     } else {
8597       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8598       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8599       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8600
8601       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8602       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8603       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8604       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8605       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8606     }
8607
8608     if(shCount >=5) {
8609       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8610       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8611     }
8612
8613     if(sign) {
8614       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8615       pic16_emitpcode(POC_BTFSC, 
8616                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8617       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8618     }
8619
8620     break;
8621
8622   case 6:
8623     if(same) {
8624
8625       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8626       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8627
8628       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8629       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8630       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8631       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8632       if(sign) {
8633         pic16_emitpcode(POC_BTFSC, 
8634                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8635         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8636       }
8637       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8638       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8639       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8640       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8641     } else {
8642       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8643       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8644       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8645       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8646       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8647       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8648       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8649       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8650       if(sign) {
8651         pic16_emitpcode(POC_BTFSC, 
8652                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8653         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8654       }
8655       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8656       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8657
8658         
8659     }
8660
8661     break;
8662   case 7:
8663     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8664     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8665     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8666     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8667     if(sign) {
8668       emitSKPNC;
8669       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8670     } else 
8671       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8672   }
8673 }
8674
8675
8676 /*-----------------------------------------------------------------*/
8677 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8678 /*-----------------------------------------------------------------*/
8679 static void shiftLLeftOrResult (operand *left, int offl,
8680                                 operand *result, int offr, int shCount)
8681 {
8682     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8683
8684     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8685     /* shift left accumulator */
8686     AccLsh(shCount);
8687     /* or with result */
8688     /* back to result */
8689     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8690 }
8691
8692 /*-----------------------------------------------------------------*/
8693 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8694 /*-----------------------------------------------------------------*/
8695 static void shiftRLeftOrResult (operand *left, int offl,
8696                                 operand *result, int offr, int shCount)
8697 {
8698     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8699     
8700     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8701     /* shift right accumulator */
8702     AccRsh(shCount, 1);
8703     /* or with result */
8704     /* back to result */
8705     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8706 }
8707
8708 /*-----------------------------------------------------------------*/
8709 /* genlshOne - left shift a one byte quantity by known count       */
8710 /*-----------------------------------------------------------------*/
8711 static void genlshOne (operand *result, operand *left, int shCount)
8712 {       
8713     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8714     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8715 }
8716
8717 /*-----------------------------------------------------------------*/
8718 /* genlshTwo - left shift two bytes by known amount != 0           */
8719 /*-----------------------------------------------------------------*/
8720 static void genlshTwo (operand *result,operand *left, int shCount)
8721 {
8722     int size;
8723     
8724     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8725     size = pic16_getDataSize(result);
8726
8727     /* if shCount >= 8 */
8728     if (shCount >= 8) {
8729         shCount -= 8 ;
8730
8731         if (size > 1){
8732             if (shCount)
8733                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8734             else 
8735                 movLeft2Result(left, LSB, result, MSB16);
8736         }
8737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8738     }
8739
8740     /*  1 <= shCount <= 7 */
8741     else {  
8742         if(size == 1)
8743             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8744         else 
8745             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8746     }
8747 }
8748
8749 /*-----------------------------------------------------------------*/
8750 /* shiftLLong - shift left one long from left to result            */
8751 /* offr = LSB or MSB16                                             */
8752 /*-----------------------------------------------------------------*/
8753 static void shiftLLong (operand *left, operand *result, int offr )
8754 {
8755     int size = AOP_SIZE(result);
8756     int same = pic16_sameRegs(AOP(left),AOP(result));
8757         int i;
8758
8759     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8760
8761         if (same && (offr == MSB16)) { //shift one byte
8762                 for(i=size-1;i>=MSB16;i--) {
8763                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8764                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8765                 }
8766         } else {
8767                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8768         }
8769         
8770     if (size > LSB+offr ){
8771                 if (same) {
8772                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8773                 } else {
8774                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8775                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8776                 }
8777          }
8778
8779     if(size > MSB16+offr){
8780                 if (same) {
8781                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8782                 } else {
8783                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8784                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8785                 }
8786     }
8787
8788     if(size > MSB24+offr){
8789                 if (same) {
8790                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8791                 } else {
8792                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8793                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8794                 }
8795     }
8796
8797     if(size > MSB32+offr){
8798                 if (same) {
8799                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8800                 } else {
8801                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8802                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8803                 }
8804     }
8805     if(offr != LSB)
8806                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8807
8808 }
8809
8810 /*-----------------------------------------------------------------*/
8811 /* genlshFour - shift four byte by a known amount != 0             */
8812 /*-----------------------------------------------------------------*/
8813 static void genlshFour (operand *result, operand *left, int shCount)
8814 {
8815     int size;
8816
8817     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8818     size = AOP_SIZE(result);
8819
8820     /* if shifting more that 3 bytes */
8821     if (shCount >= 24 ) {
8822         shCount -= 24;
8823         if (shCount)
8824             /* lowest order of left goes to the highest
8825             order of the destination */
8826             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8827         else
8828             movLeft2Result(left, LSB, result, MSB32);
8829
8830                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8831                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8832                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8833
8834         return;
8835     }
8836
8837     /* more than two bytes */
8838     else if ( shCount >= 16 ) {
8839         /* lower order two bytes goes to higher order two bytes */
8840         shCount -= 16;
8841         /* if some more remaining */
8842         if (shCount)
8843             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8844         else {
8845             movLeft2Result(left, MSB16, result, MSB32);
8846             movLeft2Result(left, LSB, result, MSB24);
8847         }
8848                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8849                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8850         return;
8851     }    
8852
8853     /* if more than 1 byte */
8854     else if ( shCount >= 8 ) {
8855         /* lower order three bytes goes to higher order  three bytes */
8856         shCount -= 8;
8857         if(size == 2){
8858             if(shCount)
8859                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8860             else
8861                 movLeft2Result(left, LSB, result, MSB16);
8862         }
8863         else{   /* size = 4 */
8864             if(shCount == 0){
8865                 movLeft2Result(left, MSB24, result, MSB32);
8866                 movLeft2Result(left, MSB16, result, MSB24);
8867                 movLeft2Result(left, LSB, result, MSB16);
8868                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8869             }
8870             else if(shCount == 1)
8871                 shiftLLong(left, result, MSB16);
8872             else{
8873                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8874                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8875                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8876                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8877             }
8878         }
8879     }
8880
8881     /* 1 <= shCount <= 7 */
8882     else if(shCount <= 3)
8883     { 
8884         shiftLLong(left, result, LSB);
8885         while(--shCount >= 1)
8886             shiftLLong(result, result, LSB);
8887     }
8888     /* 3 <= shCount <= 7, optimize */
8889     else{
8890         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8891         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8892         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8893     }
8894 }
8895
8896 /*-----------------------------------------------------------------*/
8897 /* genLeftShiftLiteral - left shifting by known count              */
8898 /*-----------------------------------------------------------------*/
8899 static void genLeftShiftLiteral (operand *left,
8900                                  operand *right,
8901                                  operand *result,
8902                                  iCode *ic)
8903 {    
8904     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8905     int size;
8906
8907     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8908     pic16_freeAsmop(right,NULL,ic,TRUE);
8909
8910     pic16_aopOp(left,ic,FALSE);
8911     pic16_aopOp(result,ic,FALSE);
8912
8913     size = getSize(operandType(result));
8914
8915 #if VIEW_SIZE
8916     pic16_emitcode("; shift left ","result %d, left %d",size,
8917              AOP_SIZE(left));
8918 #endif
8919
8920     /* I suppose that the left size >= result size */
8921     if(shCount == 0){
8922         while(size--){
8923             movLeft2Result(left, size, result, size);
8924         }
8925     }
8926
8927     else if(shCount >= (size * 8))
8928         while(size--)
8929             pic16_aopPut(AOP(result),zero,size);
8930     else{
8931         switch (size) {
8932             case 1:
8933                 genlshOne (result,left,shCount);
8934                 break;
8935
8936             case 2:
8937             case 3:
8938                 genlshTwo (result,left,shCount);
8939                 break;
8940
8941             case 4:
8942                 genlshFour (result,left,shCount);
8943                 break;
8944         }
8945     }
8946     pic16_freeAsmop(left,NULL,ic,TRUE);
8947     pic16_freeAsmop(result,NULL,ic,TRUE);
8948 }
8949
8950 /*-----------------------------------------------------------------*
8951  * genMultiAsm - repeat assembly instruction for size of register.
8952  * if endian == 1, then the high byte (i.e base address + size of 
8953  * register) is used first else the low byte is used first;
8954  *-----------------------------------------------------------------*/
8955 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8956 {
8957
8958   int offset = 0;
8959
8960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8961
8962   if(!reg)
8963     return;
8964
8965   if(!endian) {
8966     endian = 1;
8967   } else {
8968     endian = -1;
8969     offset = size-1;
8970   }
8971
8972   while(size--) {
8973     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8974     offset += endian;
8975   }
8976
8977 }
8978 /*-----------------------------------------------------------------*/
8979 /* genLeftShift - generates code for left shifting                 */
8980 /*-----------------------------------------------------------------*/
8981 static void genLeftShift (iCode *ic)
8982 {
8983   operand *left,*right, *result;
8984   int size, offset;
8985 //  char *l;
8986   symbol *tlbl , *tlbl1;
8987   pCodeOp *pctemp;
8988
8989   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8990
8991   right = IC_RIGHT(ic);
8992   left  = IC_LEFT(ic);
8993   result = IC_RESULT(ic);
8994
8995   pic16_aopOp(right,ic,FALSE);
8996
8997   /* if the shift count is known then do it 
8998      as efficiently as possible */
8999   if (AOP_TYPE(right) == AOP_LIT) {
9000     genLeftShiftLiteral (left,right,result,ic);
9001     return ;
9002   }
9003
9004   /* shift count is unknown then we have to form
9005    * a loop. Get the loop count in WREG : Note: we take
9006    * only the lower order byte since shifting
9007    * more than 32 bits make no sense anyway, ( the
9008    * largest size of an object can be only 32 bits ) */
9009   
9010   pic16_aopOp(left,ic,FALSE);
9011   pic16_aopOp(result,ic,FALSE);
9012
9013   /* now move the left to the result if they are not the
9014    * same, and if size > 1,
9015    * and if right is not same to result (!!!) -- VR */
9016   if (!pic16_sameRegs(AOP(left),AOP(result))
9017       && (AOP_SIZE(result) > 1)) {
9018
9019     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9020
9021     size = AOP_SIZE(result);
9022     offset=0;
9023     while (size--) {
9024
9025 #if 0
9026       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9027       if (*l == '@' && (IS_AOP_PREG(result))) {
9028
9029           pic16_emitcode("mov","a,%s",l);
9030           pic16_aopPut(AOP(result),"a",offset);
9031       } else
9032 #endif
9033       {
9034         /* we don't know if left is a literal or a register, take care -- VR */
9035         mov2f(AOP(result), AOP(left), offset);
9036       }
9037       offset++;
9038     }
9039   }
9040
9041   size = AOP_SIZE(result);
9042
9043   /* if it is only one byte then */
9044   if (size == 1) {
9045     if(optimized_for_speed) {
9046       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9047       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9048       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9049       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9050       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9051       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9052       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9053       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9054       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9055       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9056       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9057       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9058     } else {
9059
9060       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9061
9062       tlbl = newiTempLabel(NULL);
9063
9064 #if 1
9065       /* this is already done, why change it? */
9066       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9067                 mov2f(AOP(result), AOP(left), 0);
9068       }
9069 #endif
9070
9071       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9072       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9073       pic16_emitpLabel(tlbl->key);
9074       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9075       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9076       emitSKPC;
9077       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9078     }
9079     goto release ;
9080   }
9081     
9082   if (pic16_sameRegs(AOP(left),AOP(result))) {
9083
9084     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9085     
9086     tlbl = newiTempLabel(NULL);
9087     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9088     genMultiAsm(POC_RRCF, result, size,1);
9089     pic16_emitpLabel(tlbl->key);
9090     genMultiAsm(POC_RLCF, result, size,0);
9091     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9092     emitSKPC;
9093     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9094     goto release;
9095   }
9096
9097   //tlbl = newiTempLabel(NULL);
9098   //offset = 0 ;   
9099   //tlbl1 = newiTempLabel(NULL);
9100
9101   //reAdjustPreg(AOP(result));    
9102     
9103   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9104   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9105   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9106   //MOVA(l);
9107   //pic16_emitcode("add","a,acc");         
9108   //pic16_aopPut(AOP(result),"a",offset++);
9109   //while (--size) {
9110   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9111   //  MOVA(l);
9112   //  pic16_emitcode("rlc","a");         
9113   //  pic16_aopPut(AOP(result),"a",offset++);
9114   //}
9115   //reAdjustPreg(AOP(result));
9116
9117   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9118   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9119
9120
9121   tlbl = newiTempLabel(NULL);
9122   tlbl1= newiTempLabel(NULL);
9123
9124   size = AOP_SIZE(result);
9125   offset = 1;
9126
9127   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9128
9129   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9130
9131   /* offset should be 0, 1 or 3 */
9132   
9133   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9134   emitSKPNZ;
9135   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9136
9137   pic16_emitpcode(POC_MOVWF, pctemp);
9138
9139
9140   pic16_emitpLabel(tlbl->key);
9141
9142   emitCLRC;
9143   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9144   while(--size)
9145     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9146
9147   pic16_emitpcode(POC_DECFSZ,  pctemp);
9148   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9149   pic16_emitpLabel(tlbl1->key);
9150
9151   pic16_popReleaseTempReg(pctemp,1);
9152
9153
9154  release:
9155   pic16_freeAsmop (right,NULL,ic,TRUE);
9156   pic16_freeAsmop(left,NULL,ic,TRUE);
9157   pic16_freeAsmop(result,NULL,ic,TRUE);
9158 }
9159
9160
9161
9162 #if 0
9163 #error old code (left here for reference)
9164 /*-----------------------------------------------------------------*/
9165 /* genLeftShift - generates code for left shifting                 */
9166 /*-----------------------------------------------------------------*/
9167 static void genLeftShift (iCode *ic)
9168 {
9169   operand *left,*right, *result;
9170   int size, offset;
9171   char *l;
9172   symbol *tlbl , *tlbl1;
9173   pCodeOp *pctemp;
9174
9175   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9176
9177   right = IC_RIGHT(ic);
9178   left  = IC_LEFT(ic);
9179   result = IC_RESULT(ic);
9180
9181   pic16_aopOp(right,ic,FALSE);
9182
9183   /* if the shift count is known then do it 
9184      as efficiently as possible */
9185   if (AOP_TYPE(right) == AOP_LIT) {
9186     genLeftShiftLiteral (left,right,result,ic);
9187     return ;
9188   }
9189
9190   /* shift count is unknown then we have to form 
9191      a loop get the loop count in B : Note: we take
9192      only the lower order byte since shifting
9193      more that 32 bits make no sense anyway, ( the
9194      largest size of an object can be only 32 bits ) */  
9195
9196     
9197   pic16_aopOp(left,ic,FALSE);
9198   pic16_aopOp(result,ic,FALSE);
9199
9200   /* now move the left to the result if they are not the
9201      same */
9202   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9203       AOP_SIZE(result) > 1) {
9204
9205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9206
9207     size = AOP_SIZE(result);
9208     offset=0;
9209     while (size--) {
9210       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9211       if (*l == '@' && (IS_AOP_PREG(result))) {
9212
9213         pic16_emitcode("mov","a,%s",l);
9214         pic16_aopPut(AOP(result),"a",offset);
9215       } else {
9216
9217         /* we don't know if left is a literal or a register, take care -- VR */
9218         mov2f(AOP(result), AOP(left), offset);
9219       }
9220       offset++;
9221     }
9222   }
9223
9224   size = AOP_SIZE(result);
9225
9226   /* if it is only one byte then */
9227   if (size == 1) {
9228     if(optimized_for_speed) {
9229       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9230       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9231       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9232       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9233       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9234       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9235       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9236       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9237       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9238       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9239       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9240       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9241     } else {
9242
9243       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9244
9245       tlbl = newiTempLabel(NULL);
9246       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9247                 mov2f(AOP(result), AOP(left), 0);
9248                 
9249 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9250 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9251       }
9252
9253       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9254       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9255       pic16_emitpLabel(tlbl->key);
9256       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9257       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9258       emitSKPC;
9259       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9260     }
9261     goto release ;
9262   }
9263     
9264   if (pic16_sameRegs(AOP(left),AOP(result))) {
9265
9266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9267     
9268     tlbl = newiTempLabel(NULL);
9269     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9270     genMultiAsm(POC_RRCF, result, size,1);
9271     pic16_emitpLabel(tlbl->key);
9272     genMultiAsm(POC_RLCF, result, size,0);
9273     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9274     emitSKPC;
9275     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9276     goto release;
9277   }
9278
9279   //tlbl = newiTempLabel(NULL);
9280   //offset = 0 ;   
9281   //tlbl1 = newiTempLabel(NULL);
9282
9283   //reAdjustPreg(AOP(result));    
9284     
9285   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9286   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9287   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9288   //MOVA(l);
9289   //pic16_emitcode("add","a,acc");         
9290   //pic16_aopPut(AOP(result),"a",offset++);
9291   //while (--size) {
9292   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9293   //  MOVA(l);
9294   //  pic16_emitcode("rlc","a");         
9295   //  pic16_aopPut(AOP(result),"a",offset++);
9296   //}
9297   //reAdjustPreg(AOP(result));
9298
9299   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9300   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9301
9302
9303   tlbl = newiTempLabel(NULL);
9304   tlbl1= newiTempLabel(NULL);
9305
9306   size = AOP_SIZE(result);
9307   offset = 1;
9308
9309   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9310
9311   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9312
9313   /* offset should be 0, 1 or 3 */
9314   
9315   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9316   emitSKPNZ;
9317   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9318
9319   pic16_emitpcode(POC_MOVWF, pctemp);
9320
9321
9322   pic16_emitpLabel(tlbl->key);
9323
9324   emitCLRC;
9325   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9326   while(--size)
9327     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9328
9329   pic16_emitpcode(POC_DECFSZ,  pctemp);
9330   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9331   pic16_emitpLabel(tlbl1->key);
9332
9333   pic16_popReleaseTempReg(pctemp,1);
9334
9335
9336  release:
9337   pic16_freeAsmop (right,NULL,ic,TRUE);
9338   pic16_freeAsmop(left,NULL,ic,TRUE);
9339   pic16_freeAsmop(result,NULL,ic,TRUE);
9340 }
9341 #endif
9342
9343 /*-----------------------------------------------------------------*/
9344 /* genrshOne - right shift a one byte quantity by known count      */
9345 /*-----------------------------------------------------------------*/
9346 static void genrshOne (operand *result, operand *left,
9347                        int shCount, int sign)
9348 {
9349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9350     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9351 }
9352
9353 /*-----------------------------------------------------------------*/
9354 /* genrshTwo - right shift two bytes by known amount != 0          */
9355 /*-----------------------------------------------------------------*/
9356 static void genrshTwo (operand *result,operand *left,
9357                        int shCount, int sign)
9358 {
9359   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9360   /* if shCount >= 8 */
9361   if (shCount >= 8) {
9362     shCount -= 8 ;
9363     if (shCount)
9364       shiftR1Left2Result(left, MSB16, result, LSB,
9365                          shCount, sign);
9366     else
9367       movLeft2Result(left, MSB16, result, LSB);
9368
9369     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9370
9371     if(sign) {
9372       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9373       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9374     }
9375   }
9376
9377   /*  1 <= shCount <= 7 */
9378   else
9379     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9380 }
9381
9382 /*-----------------------------------------------------------------*/
9383 /* shiftRLong - shift right one long from left to result           */
9384 /* offl = LSB or MSB16                                             */
9385 /*-----------------------------------------------------------------*/
9386 static void shiftRLong (operand *left, int offl,
9387                         operand *result, int sign)
9388 {
9389     int size = AOP_SIZE(result);
9390     int same = pic16_sameRegs(AOP(left),AOP(result));
9391     int i;
9392     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9393
9394         if (same && (offl == MSB16)) { //shift one byte right
9395                 for(i=MSB16;i<size;i++) {
9396                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9397                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9398                 }
9399         }
9400
9401     if(sign)
9402                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9403         else
9404                 emitCLRC;
9405
9406         if (same) {
9407                 if (offl == LSB)
9408                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9409         } else {
9410         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9411         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9412         }
9413
9414     if(offl == MSB16) {
9415         /* add sign of "a" */
9416         pic16_addSign(result, MSB32, sign);
9417         }
9418
9419         if (same) {
9420         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9421         } else {
9422         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9423         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9424         }
9425         
9426         if (same) {
9427         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9428         } else {
9429         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9430         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9431         }
9432
9433         if (same) {
9434         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9435         } else {
9436         if(offl == LSB){
9437                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9438                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9439         }
9440         }
9441 }
9442
9443 /*-----------------------------------------------------------------*/
9444 /* genrshFour - shift four byte by a known amount != 0             */
9445 /*-----------------------------------------------------------------*/
9446 static void genrshFour (operand *result, operand *left,
9447                         int shCount, int sign)
9448 {
9449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9450   /* if shifting more that 3 bytes */
9451   if(shCount >= 24 ) {
9452     shCount -= 24;
9453     if(shCount)
9454       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9455     else
9456       movLeft2Result(left, MSB32, result, LSB);
9457
9458     pic16_addSign(result, MSB16, sign);
9459   }
9460   else if(shCount >= 16){
9461     shCount -= 16;
9462     if(shCount)
9463       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9464     else{
9465       movLeft2Result(left, MSB24, result, LSB);
9466       movLeft2Result(left, MSB32, result, MSB16);
9467     }
9468     pic16_addSign(result, MSB24, sign);
9469   }
9470   else if(shCount >= 8){
9471     shCount -= 8;
9472     if(shCount == 1)
9473       shiftRLong(left, MSB16, result, sign);
9474     else if(shCount == 0){
9475       movLeft2Result(left, MSB16, result, LSB);
9476       movLeft2Result(left, MSB24, result, MSB16);
9477       movLeft2Result(left, MSB32, result, MSB24);
9478       pic16_addSign(result, MSB32, sign);
9479     }
9480     else{ //shcount >= 2
9481       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9482       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9483       /* the last shift is signed */
9484       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9485       pic16_addSign(result, MSB32, sign);
9486     }
9487   }
9488   else{   /* 1 <= shCount <= 7 */
9489     if(shCount <= 2){
9490       shiftRLong(left, LSB, result, sign);
9491       if(shCount == 2)
9492         shiftRLong(result, LSB, result, sign);
9493     }
9494     else{
9495       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9496       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9497       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9498     }
9499   }
9500 }
9501
9502 /*-----------------------------------------------------------------*/
9503 /* genRightShiftLiteral - right shifting by known count            */
9504 /*-----------------------------------------------------------------*/
9505 static void genRightShiftLiteral (operand *left,
9506                                   operand *right,
9507                                   operand *result,
9508                                   iCode *ic,
9509                                   int sign)
9510 {    
9511   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9512   int lsize,res_size;
9513
9514   pic16_freeAsmop(right,NULL,ic,TRUE);
9515
9516   pic16_aopOp(left,ic,FALSE);
9517   pic16_aopOp(result,ic,FALSE);
9518
9519   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9520
9521 #if VIEW_SIZE
9522   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9523                  AOP_SIZE(left));
9524 #endif
9525
9526   lsize = pic16_getDataSize(left);
9527   res_size = pic16_getDataSize(result);
9528   /* test the LEFT size !!! */
9529
9530   /* I suppose that the left size >= result size */
9531   if(shCount == 0){
9532     while(res_size--)
9533       movLeft2Result(left, lsize, result, res_size);
9534   }
9535
9536   else if(shCount >= (lsize * 8)){
9537
9538     if(res_size == 1) {
9539       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9540       if(sign) {
9541         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9542         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9543       }
9544     } else {
9545
9546       if(sign) {
9547         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9548         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9549         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9550         while(res_size--)
9551           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9552
9553       } else {
9554
9555         while(res_size--)
9556           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9557       }
9558     }
9559   } else {
9560
9561     switch (res_size) {
9562     case 1:
9563       genrshOne (result,left,shCount,sign);
9564       break;
9565
9566     case 2:
9567       genrshTwo (result,left,shCount,sign);
9568       break;
9569
9570     case 4:
9571       genrshFour (result,left,shCount,sign);
9572       break;
9573     default :
9574       break;
9575     }
9576
9577   }
9578
9579   pic16_freeAsmop(left,NULL,ic,TRUE);
9580   pic16_freeAsmop(result,NULL,ic,TRUE);
9581 }
9582
9583 /*-----------------------------------------------------------------*/
9584 /* genSignedRightShift - right shift of signed number              */
9585 /*-----------------------------------------------------------------*/
9586 static void genSignedRightShift (iCode *ic)
9587 {
9588   operand *right, *left, *result;
9589   int size, offset;
9590   //  char *l;
9591   symbol *tlbl, *tlbl1 ;
9592   pCodeOp *pctemp;
9593
9594   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9595
9596   /* we do it the hard way put the shift count in b
9597      and loop thru preserving the sign */
9598   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9599
9600   right = IC_RIGHT(ic);
9601   left  = IC_LEFT(ic);
9602   result = IC_RESULT(ic);
9603
9604   pic16_aopOp(right,ic,FALSE);  
9605   pic16_aopOp(left,ic,FALSE);
9606   pic16_aopOp(result,ic,FALSE);
9607
9608
9609   if ( AOP_TYPE(right) == AOP_LIT) {
9610     genRightShiftLiteral (left,right,result,ic,1);
9611     return ;
9612   }
9613   /* shift count is unknown then we have to form 
9614      a loop get the loop count in B : Note: we take
9615      only the lower order byte since shifting
9616      more that 32 bits make no sense anyway, ( the
9617      largest size of an object can be only 32 bits ) */  
9618
9619   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9620   //pic16_emitcode("inc","b");
9621   //pic16_freeAsmop (right,NULL,ic,TRUE);
9622   //pic16_aopOp(left,ic,FALSE);
9623   //pic16_aopOp(result,ic,FALSE);
9624
9625   /* now move the left to the result if they are not the
9626      same */
9627   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9628       AOP_SIZE(result) > 1) {
9629
9630     size = AOP_SIZE(result);
9631     offset=0;
9632     while (size--) { 
9633       /*
9634         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9635         if (*l == '@' && IS_AOP_PREG(result)) {
9636
9637         pic16_emitcode("mov","a,%s",l);
9638         pic16_aopPut(AOP(result),"a",offset);
9639         } else
9640         pic16_aopPut(AOP(result),l,offset);
9641       */
9642       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9643       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9644
9645       offset++;
9646     }
9647   }
9648
9649   /* mov the highest order bit to OVR */    
9650   tlbl = newiTempLabel(NULL);
9651   tlbl1= newiTempLabel(NULL);
9652
9653   size = AOP_SIZE(result);
9654   offset = size - 1;
9655
9656   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9657
9658   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9659
9660   /* offset should be 0, 1 or 3 */
9661   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9662   emitSKPNZ;
9663   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9664
9665   pic16_emitpcode(POC_MOVWF, pctemp);
9666
9667
9668   pic16_emitpLabel(tlbl->key);
9669
9670   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9671   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9672
9673   while(--size) {
9674     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9675   }
9676
9677   pic16_emitpcode(POC_DECFSZ,  pctemp);
9678   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9679   pic16_emitpLabel(tlbl1->key);
9680
9681   pic16_popReleaseTempReg(pctemp,1);
9682 #if 0
9683   size = AOP_SIZE(result);
9684   offset = size - 1;
9685   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9686   pic16_emitcode("rlc","a");
9687   pic16_emitcode("mov","ov,c");
9688   /* if it is only one byte then */
9689   if (size == 1) {
9690     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9691     MOVA(l);
9692     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9693     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9694     pic16_emitcode("mov","c,ov");
9695     pic16_emitcode("rrc","a");
9696     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9697     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9698     pic16_aopPut(AOP(result),"a",0);
9699     goto release ;
9700   }
9701
9702   reAdjustPreg(AOP(result));
9703   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9704   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9705   pic16_emitcode("mov","c,ov");
9706   while (size--) {
9707     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9708     MOVA(l);
9709     pic16_emitcode("rrc","a");         
9710     pic16_aopPut(AOP(result),"a",offset--);
9711   }
9712   reAdjustPreg(AOP(result));
9713   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9714   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9715
9716  release:
9717 #endif
9718
9719   pic16_freeAsmop(left,NULL,ic,TRUE);
9720   pic16_freeAsmop(result,NULL,ic,TRUE);
9721   pic16_freeAsmop(right,NULL,ic,TRUE);
9722 }
9723
9724 /*-----------------------------------------------------------------*/
9725 /* genRightShift - generate code for right shifting                */
9726 /*-----------------------------------------------------------------*/
9727 static void genRightShift (iCode *ic)
9728 {
9729     operand *right, *left, *result;
9730     sym_link *letype ;
9731     int size, offset;
9732     char *l;
9733     symbol *tlbl, *tlbl1 ;
9734
9735     /* if signed then we do it the hard way preserve the
9736     sign bit moving it inwards */
9737     letype = getSpec(operandType(IC_LEFT(ic)));
9738     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9739
9740     if (!SPEC_USIGN(letype)) {
9741         genSignedRightShift (ic);
9742         return ;
9743     }
9744
9745     /* signed & unsigned types are treated the same : i.e. the
9746     signed is NOT propagated inwards : quoting from the
9747     ANSI - standard : "for E1 >> E2, is equivalent to division
9748     by 2**E2 if unsigned or if it has a non-negative value,
9749     otherwise the result is implementation defined ", MY definition
9750     is that the sign does not get propagated */
9751
9752     right = IC_RIGHT(ic);
9753     left  = IC_LEFT(ic);
9754     result = IC_RESULT(ic);
9755
9756     pic16_aopOp(right,ic,FALSE);
9757
9758     /* if the shift count is known then do it 
9759     as efficiently as possible */
9760     if (AOP_TYPE(right) == AOP_LIT) {
9761         genRightShiftLiteral (left,right,result,ic, 0);
9762         return ;
9763     }
9764
9765     /* shift count is unknown then we have to form 
9766     a loop get the loop count in B : Note: we take
9767     only the lower order byte since shifting
9768     more that 32 bits make no sense anyway, ( the
9769     largest size of an object can be only 32 bits ) */  
9770
9771     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9772     pic16_emitcode("inc","b");
9773     pic16_aopOp(left,ic,FALSE);
9774     pic16_aopOp(result,ic,FALSE);
9775
9776     /* now move the left to the result if they are not the
9777     same */
9778     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9779         AOP_SIZE(result) > 1) {
9780
9781         size = AOP_SIZE(result);
9782         offset=0;
9783         while (size--) {
9784             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9785             if (*l == '@' && IS_AOP_PREG(result)) {
9786
9787                 pic16_emitcode("mov","a,%s",l);
9788                 pic16_aopPut(AOP(result),"a",offset);
9789             } else
9790                 pic16_aopPut(AOP(result),l,offset);
9791             offset++;
9792         }
9793     }
9794
9795     tlbl = newiTempLabel(NULL);
9796     tlbl1= newiTempLabel(NULL);
9797     size = AOP_SIZE(result);
9798     offset = size - 1;
9799
9800     /* if it is only one byte then */
9801     if (size == 1) {
9802
9803       tlbl = newiTempLabel(NULL);
9804       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9805         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9806         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9807       }
9808
9809       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9810       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9811       pic16_emitpLabel(tlbl->key);
9812       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9813       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9814       emitSKPC;
9815       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9816
9817       goto release ;
9818     }
9819
9820     reAdjustPreg(AOP(result));
9821     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9822     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9823     CLRC;
9824     while (size--) {
9825         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9826         MOVA(l);
9827         pic16_emitcode("rrc","a");         
9828         pic16_aopPut(AOP(result),"a",offset--);
9829     }
9830     reAdjustPreg(AOP(result));
9831
9832     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9833     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9834
9835 release:
9836     pic16_freeAsmop(left,NULL,ic,TRUE);
9837     pic16_freeAsmop (right,NULL,ic,TRUE);
9838     pic16_freeAsmop(result,NULL,ic,TRUE);
9839 }
9840
9841
9842 void pic16_loadFSR0(operand *op)
9843 {
9844         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9845 }
9846
9847 /*-----------------------------------------------------------------*/
9848 /* genUnpackBits - generates code for unpacking bits               */
9849 /*-----------------------------------------------------------------*/
9850 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9851 {    
9852     int shCnt ;
9853     int rlen = 0 ;
9854     sym_link *etype;
9855     int offset = 0 ;
9856
9857         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9858         etype = getSpec(operandType(result));
9859
9860         /* the following call to pic16_loadFSR0 is temporary until
9861          * optimization to handle single bit assignments is added
9862          * to the function. Until then use the old safe way! -- VR */
9863         pic16_loadFSR0( left );
9864  
9865         /* read the first byte  */
9866         switch (ptype) {
9867                 case POINTER:
9868                 case IPOINTER:
9869                 case PPOINTER:
9870                 case FPOINTER:
9871                 case GPOINTER:
9872                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9873                         break;
9874                 case CPOINTER:
9875                         pic16_emitcode("clr","a");
9876                         pic16_emitcode("movc","a","@a+dptr");
9877                         break;
9878         }
9879         
9880
9881         /* if we have bitdisplacement then it fits   */
9882         /* into this byte completely or if length is */
9883         /* less than a byte                          */
9884         if ((shCnt = SPEC_BSTR(etype)) || 
9885                 (SPEC_BLEN(etype) <= 8))  {
9886
9887                 /* shift right acc */
9888                 AccRsh(shCnt, 0);
9889
9890                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9891                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9892
9893 /* VR -- normally I would use the following, but since we use the hack,
9894  * to avoid the masking from AccRsh, why not mask it right now? */
9895
9896 /*
9897                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9898 */
9899
9900                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9901           return ;
9902         }
9903
9904
9905
9906         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9907         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9908         exit(-1);
9909
9910     /* bit field did not fit in a byte  */
9911     rlen = SPEC_BLEN(etype) - 8;
9912     pic16_aopPut(AOP(result),"a",offset++);
9913
9914     while (1)  {
9915
9916         switch (ptype) {
9917         case POINTER:
9918         case IPOINTER:
9919             pic16_emitcode("inc","%s",rname);
9920             pic16_emitcode("mov","a,@%s",rname);
9921             break;
9922             
9923         case PPOINTER:
9924             pic16_emitcode("inc","%s",rname);
9925             pic16_emitcode("movx","a,@%s",rname);
9926             break;
9927
9928         case FPOINTER:
9929             pic16_emitcode("inc","dptr");
9930             pic16_emitcode("movx","a,@dptr");
9931             break;
9932             
9933         case CPOINTER:
9934             pic16_emitcode("clr","a");
9935             pic16_emitcode("inc","dptr");
9936             pic16_emitcode("movc","a","@a+dptr");
9937             break;
9938             
9939         case GPOINTER:
9940             pic16_emitcode("inc","dptr");
9941             pic16_emitcode("lcall","__gptrget");
9942             break;
9943         }
9944
9945         rlen -= 8;            
9946         /* if we are done */
9947         if ( rlen <= 0 )
9948             break ;
9949         
9950         pic16_aopPut(AOP(result),"a",offset++);
9951                               
9952     }
9953     
9954     if (rlen) {
9955         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9956         pic16_aopPut(AOP(result),"a",offset);          
9957     }
9958     
9959     return ;
9960 }
9961
9962
9963 static void genDataPointerGet(operand *left,
9964                               operand *result,
9965                               iCode *ic)
9966 {
9967   int size, offset = 0, leoffset=0 ;
9968
9969         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9970         pic16_aopOp(result, ic, FALSE);
9971
9972         size = AOP_SIZE(result);
9973 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9974
9975
9976 #if 0
9977         /* The following tests may save a redudant movff instruction when
9978          * accessing unions */
9979          
9980         /* if they are the same */
9981         if (operandsEqu (left, result)) {
9982                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9983                 goto release;
9984         }
9985 #endif
9986
9987 #if 0
9988         /* if they are the same registers */
9989         if (pic16_sameRegs(AOP(left),AOP(result))) {
9990                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9991                 goto release;
9992         }
9993 #endif
9994
9995 #if 1
9996         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9997                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9998                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9999                 goto release;
10000         }
10001 #endif
10002
10003
10004 #if 0
10005         if ( AOP_TYPE(left) == AOP_PCODE) {
10006                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10007                                 AOP(left)->aopu.pcop->name,
10008                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10009                                 PCOR(AOP(left)->aopu.pcop)->instance:
10010                                 PCOI(AOP(left)->aopu.pcop)->offset);
10011         }
10012 #endif
10013
10014         if(AOP(left)->aopu.pcop->type == PO_DIR)
10015                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10016
10017         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10018
10019         while (size--) {
10020                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10021                 
10022                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10023                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10024                         mov2w(AOP(left), offset); // patch 8
10025                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10026                 } else {
10027                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10028                                 pic16_popGet(AOP(left), offset), //patch 8
10029                                 pic16_popGet(AOP(result), offset)));
10030                 }
10031
10032                 offset++;
10033                 leoffset++;
10034         }
10035
10036 release:
10037     pic16_freeAsmop(result,NULL,ic,TRUE);
10038 }
10039
10040
10041
10042 /*-----------------------------------------------------------------*/
10043 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10044 /*-----------------------------------------------------------------*/
10045 static void genNearPointerGet (operand *left, 
10046                                operand *result, 
10047                                iCode *ic)
10048 {
10049     asmop *aop = NULL;
10050     //regs *preg = NULL ;
10051     sym_link *rtype, *retype;
10052     sym_link *ltype = operandType(left);    
10053
10054         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10055         rtype = operandType(result);
10056         retype= getSpec(rtype);
10057     
10058         pic16_aopOp(left,ic,FALSE);
10059
10060 //      pic16_DumpOp("(left)",left);
10061 //      pic16_DumpOp("(result)",result);
10062
10063         /* if left is rematerialisable and
10064          * result is not bit variable type and
10065          * the left is pointer to data space i.e
10066          * lower 128 bytes of space */
10067         if (AOP_TYPE(left) == AOP_PCODE
10068                 && !IS_BITFIELD(retype)
10069                 && DCL_TYPE(ltype) == POINTER) {
10070
10071                 genDataPointerGet (left,result,ic);
10072                 pic16_freeAsmop(left, NULL, ic, TRUE);
10073           return ;
10074         }
10075     
10076         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10077
10078         /* if the value is already in a pointer register
10079          * then don't need anything more */
10080         if (!AOP_INPREG(AOP(left))) {
10081                 /* otherwise get a free pointer register */
10082                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10083                 
10084                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10085                 if( (AOP_TYPE(left) == AOP_PCODE) 
10086                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10087                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
10088                 {
10089                         if(!IS_BITFIELD(retype))
10090                                 pic16_loadFSR0( left );  // patch 10
10091                 } else {
10092                         // set up FSR0 with address from left
10093                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10094                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10095                 }
10096         }
10097 //       else
10098 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10099     
10100         pic16_aopOp (result,ic,FALSE);
10101     
10102       /* if bitfield then unpack the bits */
10103     if (IS_BITFIELD(retype)) 
10104         genUnpackBits (result, left, NULL, POINTER);
10105     else {
10106         /* we have can just get the values */
10107       int size = AOP_SIZE(result);
10108       int offset = 0;   
10109         
10110       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10111
10112
10113         /* fsr0 is loaded already -- VR */
10114 //      pic16_loadFSR0( left );
10115
10116 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10117 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10118       while(size--) {
10119
10120         if(size) {
10121                 pic16_emitpcode(POC_MOVFF,
10122                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10123                                 pic16_popGet(AOP(result), offset++)));
10124         } else {
10125                 pic16_emitpcode(POC_MOVFF,
10126                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10127                                 pic16_popGet(AOP(result), offset++)));
10128         }
10129       }
10130 #if 0
10131 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10132 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10133         if(size)
10134           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10135 #endif
10136 /*
10137         while (size--) {
10138             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10139
10140                 pic16_emitcode("mov","a,@%s",rname);
10141                 pic16_aopPut(AOP(result),"a",offset);
10142             } else {
10143                 sprintf(buffer,"@%s",rname);
10144                 pic16_aopPut(AOP(result),buffer,offset);
10145             }
10146             offset++ ;
10147             if (size)
10148                 pic16_emitcode("inc","%s",rname);
10149         }
10150 */
10151     }
10152
10153     /* now some housekeeping stuff */
10154     if (aop) {
10155         /* we had to allocate for this iCode */
10156     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10157         pic16_freeAsmop(NULL,aop,ic,TRUE);
10158     } else { 
10159         /* we did not allocate which means left
10160            already in a pointer register, then
10161            if size > 0 && this could be used again
10162            we have to point it back to where it 
10163            belongs */
10164     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10165         if (AOP_SIZE(result) > 1 &&
10166             !OP_SYMBOL(left)->remat &&
10167             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10168               ic->depth )) {
10169 //          int size = AOP_SIZE(result) - 1;
10170 //          while (size--)
10171 //              pic16_emitcode("dec","%s",rname);
10172         }
10173     }
10174
10175     /* done */
10176     pic16_freeAsmop(left,NULL,ic,TRUE);
10177     pic16_freeAsmop(result,NULL,ic,TRUE);
10178      
10179 }
10180
10181 /*-----------------------------------------------------------------*/
10182 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10183 /*-----------------------------------------------------------------*/
10184 static void genPagedPointerGet (operand *left, 
10185                                operand *result, 
10186                                iCode *ic)
10187 {
10188     asmop *aop = NULL;
10189     regs *preg = NULL ;
10190     char *rname ;
10191     sym_link *rtype, *retype;    
10192
10193     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10194
10195     rtype = operandType(result);
10196     retype= getSpec(rtype);
10197     
10198     pic16_aopOp(left,ic,FALSE);
10199
10200   /* if the value is already in a pointer register
10201        then don't need anything more */
10202     if (!AOP_INPREG(AOP(left))) {
10203         /* otherwise get a free pointer register */
10204         aop = newAsmop(0);
10205         preg = getFreePtr(ic,&aop,FALSE);
10206         pic16_emitcode("mov","%s,%s",
10207                 preg->name,
10208                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10209         rname = preg->name ;
10210     } else
10211         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10212     
10213     pic16_freeAsmop(left,NULL,ic,TRUE);
10214     pic16_aopOp (result,ic,FALSE);
10215
10216     /* if bitfield then unpack the bits */
10217     if (IS_BITFIELD(retype)) 
10218         genUnpackBits (result,left,rname,PPOINTER);
10219     else {
10220         /* we have can just get the values */
10221         int size = AOP_SIZE(result);
10222         int offset = 0 ;        
10223         
10224         while (size--) {
10225             
10226             pic16_emitcode("movx","a,@%s",rname);
10227             pic16_aopPut(AOP(result),"a",offset);
10228             
10229             offset++ ;
10230             
10231             if (size)
10232                 pic16_emitcode("inc","%s",rname);
10233         }
10234     }
10235
10236     /* now some housekeeping stuff */
10237     if (aop) {
10238         /* we had to allocate for this iCode */
10239         pic16_freeAsmop(NULL,aop,ic,TRUE);
10240     } else { 
10241         /* we did not allocate which means left
10242            already in a pointer register, then
10243            if size > 0 && this could be used again
10244            we have to point it back to where it 
10245            belongs */
10246         if (AOP_SIZE(result) > 1 &&
10247             !OP_SYMBOL(left)->remat &&
10248             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10249               ic->depth )) {
10250             int size = AOP_SIZE(result) - 1;
10251             while (size--)
10252                 pic16_emitcode("dec","%s",rname);
10253         }
10254     }
10255
10256     /* done */
10257     pic16_freeAsmop(result,NULL,ic,TRUE);
10258     
10259         
10260 }
10261
10262 /*-----------------------------------------------------------------*/
10263 /* genFarPointerGet - gget value from far space                    */
10264 /*-----------------------------------------------------------------*/
10265 static void genFarPointerGet (operand *left,
10266                               operand *result, iCode *ic)
10267 {
10268     int size, offset ;
10269     sym_link *retype = getSpec(operandType(result));
10270
10271     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10272
10273     pic16_aopOp(left,ic,FALSE);
10274
10275     /* if the operand is already in dptr 
10276     then we do nothing else we move the value to dptr */
10277     if (AOP_TYPE(left) != AOP_STR) {
10278         /* if this is remateriazable */
10279         if (AOP_TYPE(left) == AOP_IMMD)
10280             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10281         else { /* we need to get it byte by byte */
10282             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10283             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10284             if (options.model == MODEL_FLAT24)
10285             {
10286                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10287             }
10288         }
10289     }
10290     /* so dptr know contains the address */
10291     pic16_freeAsmop(left,NULL,ic,TRUE);
10292     pic16_aopOp(result,ic,FALSE);
10293
10294     /* if bit then unpack */
10295     if (IS_BITFIELD(retype)) 
10296         genUnpackBits(result,left,"dptr",FPOINTER);
10297     else {
10298         size = AOP_SIZE(result);
10299         offset = 0 ;
10300
10301         while (size--) {
10302             pic16_emitcode("movx","a,@dptr");
10303             pic16_aopPut(AOP(result),"a",offset++);
10304             if (size)
10305                 pic16_emitcode("inc","dptr");
10306         }
10307     }
10308
10309     pic16_freeAsmop(result,NULL,ic,TRUE);
10310 }
10311 #if 0
10312 /*-----------------------------------------------------------------*/
10313 /* genCodePointerGet - get value from code space                  */
10314 /*-----------------------------------------------------------------*/
10315 static void genCodePointerGet (operand *left,
10316                                 operand *result, iCode *ic)
10317 {
10318     int size, offset ;
10319     sym_link *retype = getSpec(operandType(result));
10320
10321     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10322
10323     pic16_aopOp(left,ic,FALSE);
10324
10325     /* if the operand is already in dptr 
10326     then we do nothing else we move the value to dptr */
10327     if (AOP_TYPE(left) != AOP_STR) {
10328         /* if this is remateriazable */
10329         if (AOP_TYPE(left) == AOP_IMMD)
10330             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10331         else { /* we need to get it byte by byte */
10332             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10333             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10334             if (options.model == MODEL_FLAT24)
10335             {
10336                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10337             }
10338         }
10339     }
10340     /* so dptr know contains the address */
10341     pic16_freeAsmop(left,NULL,ic,TRUE);
10342     pic16_aopOp(result,ic,FALSE);
10343
10344     /* if bit then unpack */
10345     if (IS_BITFIELD(retype)) 
10346         genUnpackBits(result,left,"dptr",CPOINTER);
10347     else {
10348         size = AOP_SIZE(result);
10349         offset = 0 ;
10350
10351         while (size--) {
10352             pic16_emitcode("clr","a");
10353             pic16_emitcode("movc","a,@a+dptr");
10354             pic16_aopPut(AOP(result),"a",offset++);
10355             if (size)
10356                 pic16_emitcode("inc","dptr");
10357         }
10358     }
10359
10360     pic16_freeAsmop(result,NULL,ic,TRUE);
10361 }
10362 #endif
10363 #if 0
10364 /*-----------------------------------------------------------------*/
10365 /* genGenPointerGet - gget value from generic pointer space        */
10366 /*-----------------------------------------------------------------*/
10367 static void genGenPointerGet (operand *left,
10368                               operand *result, iCode *ic)
10369 {
10370   int size, offset, lit;
10371   sym_link *retype = getSpec(operandType(result));
10372
10373         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10374         pic16_aopOp(left,ic,FALSE);
10375         pic16_aopOp(result,ic,FALSE);
10376         size = AOP_SIZE(result);
10377
10378         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10379
10380         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10381
10382                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10383                 // load FSR0 from immediate
10384                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10385
10386 //              pic16_loadFSR0( left );
10387
10388                 offset = 0;
10389                 while(size--) {
10390                         if(size) {
10391                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10392                         } else {
10393                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10394                         }
10395                         offset++;
10396                 }
10397                 goto release;
10398
10399         }
10400         else { /* we need to get it byte by byte */
10401                 // set up FSR0 with address from left
10402                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10403                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10404
10405                 offset = 0 ;
10406
10407                 while(size--) {
10408                         if(size) {
10409                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10410                         } else {
10411                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10412                         }
10413                         offset++;
10414                 }
10415                 goto release;
10416         }
10417
10418   /* if bit then unpack */
10419         if (IS_BITFIELD(retype)) 
10420                 genUnpackBits(result,left,"BAD",GPOINTER);
10421
10422         release:
10423         pic16_freeAsmop(left,NULL,ic,TRUE);
10424         pic16_freeAsmop(result,NULL,ic,TRUE);
10425
10426 }
10427 #endif
10428
10429
10430 /*-----------------------------------------------------------------*/
10431 /* genGenPointerGet - gget value from generic pointer space        */
10432 /*-----------------------------------------------------------------*/
10433 static void genGenPointerGet (operand *left,
10434                               operand *result, iCode *ic)
10435 {
10436   int size, offset, lit;
10437   sym_link *retype = getSpec(operandType(result));
10438   char fgptrget[32];
10439
10440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10441     pic16_aopOp(left,ic,FALSE);
10442     pic16_aopOp(result,ic,FALSE);
10443     size = AOP_SIZE(result);
10444
10445     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10446
10447     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10448
10449       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10450       // load FSR0 from immediate
10451       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10452
10453       werror(W_POSSBUG2, __FILE__, __LINE__);
10454
10455       offset = 0;
10456       while(size--) {
10457         if(size) {
10458           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10459         } else {
10460           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10461         }
10462         offset++;
10463       }
10464
10465       goto release;
10466
10467     } else { /* we need to get it byte by byte */
10468
10469       /* set up WREG:PRODL:FSR0L with address from left */
10470       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10471       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10472       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10473       
10474       switch( size ) {
10475         case 1: strcpy(fgptrget, "__gptrget1"); break;
10476         case 2: strcpy(fgptrget, "__gptrget2"); break;
10477         case 3: strcpy(fgptrget, "__gptrget3"); break;
10478         case 4: strcpy(fgptrget, "__gptrget4"); break;
10479         default:
10480           werror(W_POSSBUG2, __FILE__, __LINE__);
10481           abort();
10482       }
10483       
10484       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10485       
10486       assignResultValue(result, 1);
10487       
10488       {
10489         symbol *sym;
10490
10491           sym = newSymbol( fgptrget, 0 );
10492           strcpy(sym->rname, fgptrget);
10493           checkAddSym(&externs, sym);
10494
10495 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10496       }
10497               
10498       goto release;
10499     }
10500
10501   /* if bit then unpack */
10502     if (IS_BITFIELD(retype)) 
10503       genUnpackBits(result,left,"BAD",GPOINTER);
10504
10505 release:
10506   pic16_freeAsmop(left,NULL,ic,TRUE);
10507   pic16_freeAsmop(result,NULL,ic,TRUE);
10508 }
10509
10510 /*-----------------------------------------------------------------*/
10511 /* genConstPointerGet - get value from const generic pointer space */
10512 /*-----------------------------------------------------------------*/
10513 static void genConstPointerGet (operand *left,
10514                                 operand *result, iCode *ic)
10515 {
10516   //sym_link *retype = getSpec(operandType(result));
10517   // symbol *albl = newiTempLabel(NULL);        // patch 15
10518   // symbol *blbl = newiTempLabel(NULL);        //
10519   // PIC_OPCODE poc;                            // patch 15
10520   int size;
10521   int offset = 0;
10522
10523   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10524   pic16_aopOp(left,ic,FALSE);
10525   pic16_aopOp(result,ic,TRUE);
10526   size = AOP_SIZE(result);
10527
10528   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10529
10530   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10531 #if 0                                                                   // patch 15
10532   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10533   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10534   pic16_emitpLabel(albl->key);
10535
10536   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10537   
10538   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10539   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10540   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10541   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10542   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10543
10544   pic16_emitpLabel(blbl->key);
10545
10546   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10547 #endif                                                                  // patch 15
10548
10549
10550   // set up table pointer
10551   if( (AOP_TYPE(left) == AOP_PCODE) 
10552       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10553           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
10554     {
10555       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10556       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10557       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10558       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10559       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10560       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10561     }
10562   else
10563     {
10564       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10565       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10566       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10567     }
10568
10569
10570   while(size--)
10571     {
10572       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10573       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10574       offset++;
10575     }
10576     
10577   pic16_freeAsmop(left,NULL,ic,TRUE);
10578   pic16_freeAsmop(result,NULL,ic,TRUE);
10579
10580 }
10581
10582
10583 /*-----------------------------------------------------------------*/
10584 /* genPointerGet - generate code for pointer get                   */
10585 /*-----------------------------------------------------------------*/
10586 static void genPointerGet (iCode *ic)
10587 {
10588     operand *left, *result ;
10589     sym_link *type, *etype;
10590     int p_type;
10591
10592     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10593
10594     left = IC_LEFT(ic);
10595     result = IC_RESULT(ic) ;
10596
10597     /* depending on the type of pointer we need to
10598     move it to the correct pointer register */
10599     type = operandType(left);
10600     etype = getSpec(type);
10601
10602 #if 0
10603     if (IS_PTR_CONST(type))
10604 #else
10605     if (IS_CODEPTR(type))
10606 #endif
10607       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10608
10609     /* if left is of type of pointer then it is simple */
10610     if (IS_PTR(type) && !IS_FUNC(type->next)) 
10611         p_type = DCL_TYPE(type);
10612     else {
10613         /* we have to go by the storage class */
10614         p_type = PTR_TYPE(SPEC_OCLS(etype));
10615
10616         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10617
10618         if (SPEC_OCLS(etype)->codesp ) {
10619           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10620           //p_type = CPOINTER ; 
10621         }
10622         else
10623             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10624               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10625                /*p_type = FPOINTER ;*/ 
10626             else
10627                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10628                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10629 /*                  p_type = PPOINTER; */
10630                 else
10631                     if (SPEC_OCLS(etype) == idata )
10632                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10633 /*                      p_type = IPOINTER; */
10634                     else
10635                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10636 /*                      p_type = POINTER ; */
10637     }
10638
10639     /* now that we have the pointer type we assign
10640     the pointer values */
10641     switch (p_type) {
10642
10643     case POINTER:       
10644     case IPOINTER:
10645         genNearPointerGet (left,result,ic);
10646         break;
10647
10648     case PPOINTER:
10649         genPagedPointerGet(left,result,ic);
10650         break;
10651
10652     case FPOINTER:
10653         genFarPointerGet (left,result,ic);
10654         break;
10655
10656     case CPOINTER:
10657         genConstPointerGet (left,result,ic);
10658         //pic16_emitcodePointerGet (left,result,ic);
10659         break;
10660
10661     case GPOINTER:
10662 #if 0
10663       if (IS_PTR_CONST(type))
10664         genConstPointerGet (left,result,ic);
10665       else
10666 #endif
10667         genGenPointerGet (left,result,ic);
10668       break;
10669
10670     default:
10671       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10672               "genPointerGet: illegal pointer type");
10673     
10674     }
10675
10676 }
10677
10678 /*-----------------------------------------------------------------*/
10679 /* genPackBits - generates code for packed bit storage             */
10680 /*-----------------------------------------------------------------*/
10681 static void genPackBits (sym_link    *etype , operand *result,
10682                          operand *right ,
10683                          char *rname, int p_type)
10684 {
10685   int shCnt = 0 ;
10686   int offset = 0  ;
10687   int rLen = 0 ;
10688   int blen, bstr ;   
10689   char *l ;
10690
10691         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10692         blen = SPEC_BLEN(etype);
10693         bstr = SPEC_BSTR(etype);
10694
10695         if(AOP_TYPE(right) == AOP_LIT) {
10696                 if((blen == 1) && (bstr < 8)) {
10697                   unsigned long lit;
10698                         /* it is a single bit, so use the appropriate bit instructions */
10699
10700                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10701
10702                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10703 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10704                         if((p_type == POINTER) && (result)) {
10705                                 /* workaround to reduce the extra lfsr instruction */
10706                                 if(lit) {
10707                                         pic16_emitpcode(POC_BSF,
10708                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10709                                 } else {
10710                                         pic16_emitpcode(POC_BCF,
10711                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10712                                 }
10713                         } else {
10714
10715                                 if(lit) {
10716                                         pic16_emitpcode(POC_BSF,
10717                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10718                                 } else {
10719                                         pic16_emitpcode(POC_BCF,
10720                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10721                                 }
10722                         }
10723         
10724                   return;
10725                 }
10726
10727                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10728                 offset++;
10729         } else
10730                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10731
10732         /* if the bit lenth is less than or    */
10733         /* it exactly fits a byte then         */
10734         if((shCnt=SPEC_BSTR(etype))
10735                 || SPEC_BLEN(etype) <= 8 )  {
10736
10737                 /* shift left acc */
10738                 AccLsh(shCnt);
10739
10740                 /* using PRODL as a temporary register here */
10741                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10742
10743                 switch (p_type) {
10744                         case FPOINTER:
10745                         case POINTER:
10746                         case GPOINTER:
10747                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10748 //                              pic16_emitcode ("mov","b,a");
10749 //                              pic16_emitcode("mov","a,@%s",rname);
10750                                 break;
10751                 }
10752 #if 1
10753                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10754                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10755                                         (unsigned char)(0xff >> (8-bstr))) ));
10756                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10757                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10758 #endif
10759
10760           return;
10761         }
10762
10763
10764         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10765         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10766         exit(-1);
10767
10768
10769     /* if we r done */
10770     if ( SPEC_BLEN(etype) <= 8 )
10771         return ;
10772
10773     pic16_emitcode("inc","%s",rname);
10774     rLen = SPEC_BLEN(etype) ;     
10775
10776
10777
10778     /* now generate for lengths greater than one byte */
10779     while (1) {
10780
10781         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10782
10783         rLen -= 8 ;
10784         if (rLen <= 0 )
10785             break ;
10786
10787         switch (p_type) {
10788             case POINTER:
10789                 if (*l == '@') {
10790                     MOVA(l);
10791                     pic16_emitcode("mov","@%s,a",rname);
10792                 } else
10793                     pic16_emitcode("mov","@%s,%s",rname,l);
10794                 break;
10795
10796             case FPOINTER:
10797                 MOVA(l);
10798                 pic16_emitcode("movx","@dptr,a");
10799                 break;
10800
10801             case GPOINTER:
10802                 MOVA(l);
10803                 DEBUGpic16_emitcode(";lcall","__gptrput");
10804                 break;  
10805         }   
10806         pic16_emitcode ("inc","%s",rname);
10807     }
10808
10809     MOVA(l);
10810
10811     /* last last was not complete */
10812     if (rLen)   {
10813         /* save the byte & read byte */
10814         switch (p_type) {
10815             case POINTER:
10816                 pic16_emitcode ("mov","b,a");
10817                 pic16_emitcode("mov","a,@%s",rname);
10818                 break;
10819
10820             case FPOINTER:
10821                 pic16_emitcode ("mov","b,a");
10822                 pic16_emitcode("movx","a,@dptr");
10823                 break;
10824
10825             case GPOINTER:
10826                 pic16_emitcode ("push","b");
10827                 pic16_emitcode ("push","acc");
10828                 pic16_emitcode ("lcall","__gptrget");
10829                 pic16_emitcode ("pop","b");
10830                 break;
10831         }
10832
10833         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10834         pic16_emitcode ("orl","a,b");
10835     }
10836
10837     if (p_type == GPOINTER)
10838         pic16_emitcode("pop","b");
10839
10840     switch (p_type) {
10841
10842     case POINTER:
10843         pic16_emitcode("mov","@%s,a",rname);
10844         break;
10845         
10846     case FPOINTER:
10847         pic16_emitcode("movx","@dptr,a");
10848         break;
10849         
10850     case GPOINTER:
10851         DEBUGpic16_emitcode(";lcall","__gptrput");
10852         break;                  
10853     }
10854 }
10855 /*-----------------------------------------------------------------*/
10856 /* genDataPointerSet - remat pointer to data space                 */
10857 /*-----------------------------------------------------------------*/
10858 static void genDataPointerSet(operand *right,
10859                               operand *result,
10860                               iCode *ic)
10861 {
10862     int size, offset = 0, resoffset=0 ;
10863
10864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10865     pic16_aopOp(right,ic,FALSE);
10866
10867     size = AOP_SIZE(right);
10868
10869 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10870
10871 #if 0
10872     if ( AOP_TYPE(result) == AOP_PCODE) {
10873       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10874               AOP(result)->aopu.pcop->name,
10875                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10876               PCOR(AOP(result)->aopu.pcop)->instance:
10877               PCOI(AOP(result)->aopu.pcop)->offset);
10878     }
10879 #endif
10880
10881         if(AOP(result)->aopu.pcop->type == PO_DIR)
10882                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10883
10884         while (size--) {
10885                 if (AOP_TYPE(right) == AOP_LIT) {
10886                   unsigned int lit;
10887
10888                     if(!IS_FLOAT(operandType( right )))
10889                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10890                     else {
10891                       union {
10892                         unsigned long lit_int;
10893                         float lit_float;
10894                       } info;
10895         
10896                         /* take care if literal is a float */
10897                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10898                         lit = info.lit_int;
10899                     }
10900
10901                     lit = lit >> (8*offset);
10902                     if(lit&0xff) {
10903                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10904                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10905                     } else {
10906                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10907                     }
10908                 } else {
10909                   mov2w(AOP(right), offset);
10910                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10911                 }
10912                 offset++;
10913                 resoffset++;
10914         }
10915
10916     pic16_freeAsmop(right,NULL,ic,TRUE);
10917 }
10918
10919
10920
10921 /*-----------------------------------------------------------------*/
10922 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10923 /*-----------------------------------------------------------------*/
10924 static void genNearPointerSet (operand *right,
10925                                operand *result, 
10926                                iCode *ic)
10927 {
10928   asmop *aop = NULL;
10929   char *l;
10930   sym_link *retype;
10931   sym_link *ptype = operandType(result);
10932   sym_link *resetype;
10933     
10934         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10935         retype= getSpec(operandType(right));
10936         resetype = getSpec(operandType(result));
10937   
10938         pic16_aopOp(result,ic,FALSE);
10939     
10940         /* if the result is rematerializable &
10941          * in data space & not a bit variable */
10942         
10943         /* and result is not a bit variable */
10944         if (AOP_TYPE(result) == AOP_PCODE
10945 //              && AOP_TYPE(result) == AOP_IMMD
10946                 && DCL_TYPE(ptype) == POINTER
10947                 && !IS_BITFIELD(retype)
10948                 && !IS_BITFIELD(resetype)) {
10949
10950                 genDataPointerSet (right,result,ic);
10951                 pic16_freeAsmop(result,NULL,ic,TRUE);
10952           return;
10953         }
10954
10955         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10956         pic16_aopOp(right,ic,FALSE);
10957         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10958
10959         /* if the value is already in a pointer register
10960          * then don't need anything more */
10961         if (!AOP_INPREG(AOP(result))) {
10962                 /* otherwise get a free pointer register */
10963                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10964
10965                 if( (AOP_TYPE(result) == AOP_PCODE) 
10966                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10967                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10968                 {
10969                   if(!IS_BITFIELD(resetype))
10970                         pic16_loadFSR0( result );  // patch 10
10971                 } else {
10972                         // set up FSR0 with address of result
10973                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10974                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10975                 }
10976
10977         }
10978 //      else
10979 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10980
10981         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10982
10983         /* if bitfield then unpack the bits */
10984         if (IS_BITFIELD(resetype)) {
10985                 genPackBits (resetype, result, right, NULL, POINTER);
10986         } else {
10987                 /* we have can just get the values */
10988           int size = AOP_SIZE(right);
10989           int offset = 0 ;    
10990
10991                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10992                 while (size--) {
10993                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10994                         if (*l == '@' ) {
10995                                 //MOVA(l);
10996                                 //pic16_emitcode("mov","@%s,a",rname);
10997                                 pic16_emitcode("movf","indf0,w ;1");
10998                         } else {
10999
11000                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11001                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11002                                         if (size) {                                                                     // 
11003                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11004                                         } else {                                                                        // 
11005                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11006                                         }                                                                               // 
11007                                 } else { // no literal                                                                  // 
11008                                         if(size) {                                                                      // 
11009                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11010                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11011                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11012                                         } else {                                                                        // 
11013                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11014                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11015                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11016                                         }                                                                               //
11017                                 }                                                                                       // patch 10
11018                         }
11019                         offset++;
11020                 }
11021         }
11022
11023         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11024         /* now some housekeeping stuff */
11025         if (aop) {
11026                 /* we had to allocate for this iCode */
11027                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11028         } else { 
11029                 /* we did not allocate which means left
11030                  * already in a pointer register, then
11031                  * if size > 0 && this could be used again
11032                  * we have to point it back to where it 
11033                  * belongs */
11034                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11035                 if (AOP_SIZE(right) > 1
11036                         && !OP_SYMBOL(result)->remat
11037                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11038                                 || ic->depth )) {
11039
11040                   int size = AOP_SIZE(right) - 1;
11041
11042                         while (size--)
11043                                 pic16_emitcode("decf","fsr0,f");
11044                         //pic16_emitcode("dec","%s",rname);
11045                 }
11046         }
11047
11048         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11049         /* done */
11050 //release:
11051         pic16_freeAsmop(right,NULL,ic,TRUE);
11052         pic16_freeAsmop(result,NULL,ic,TRUE);
11053 }
11054
11055 /*-----------------------------------------------------------------*/
11056 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11057 /*-----------------------------------------------------------------*/
11058 static void genPagedPointerSet (operand *right,
11059                                operand *result, 
11060                                iCode *ic)
11061 {
11062     asmop *aop = NULL;
11063     regs *preg = NULL ;
11064     char *rname , *l;
11065     sym_link *retype;
11066        
11067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11068
11069     retype= getSpec(operandType(right));
11070     
11071     pic16_aopOp(result,ic,FALSE);
11072     
11073     /* if the value is already in a pointer register
11074        then don't need anything more */
11075     if (!AOP_INPREG(AOP(result))) {
11076         /* otherwise get a free pointer register */
11077         aop = newAsmop(0);
11078         preg = getFreePtr(ic,&aop,FALSE);
11079         pic16_emitcode("mov","%s,%s",
11080                 preg->name,
11081                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11082         rname = preg->name ;
11083     } else
11084         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11085     
11086     pic16_freeAsmop(result,NULL,ic,TRUE);
11087     pic16_aopOp (right,ic,FALSE);
11088
11089     /* if bitfield then unpack the bits */
11090     if (IS_BITFIELD(retype)) 
11091         genPackBits (retype,result,right,rname,PPOINTER);
11092     else {
11093         /* we have can just get the values */
11094         int size = AOP_SIZE(right);
11095         int offset = 0 ;        
11096         
11097         while (size--) {
11098             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11099             
11100             MOVA(l);
11101             pic16_emitcode("movx","@%s,a",rname);
11102
11103             if (size)
11104                 pic16_emitcode("inc","%s",rname);
11105
11106             offset++;
11107         }
11108     }
11109     
11110     /* now some housekeeping stuff */
11111     if (aop) {
11112         /* we had to allocate for this iCode */
11113         pic16_freeAsmop(NULL,aop,ic,TRUE);
11114     } else { 
11115         /* we did not allocate which means left
11116            already in a pointer register, then
11117            if size > 0 && this could be used again
11118            we have to point it back to where it 
11119            belongs */
11120         if (AOP_SIZE(right) > 1 &&
11121             !OP_SYMBOL(result)->remat &&
11122             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11123               ic->depth )) {
11124             int size = AOP_SIZE(right) - 1;
11125             while (size--)
11126                 pic16_emitcode("dec","%s",rname);
11127         }
11128     }
11129
11130     /* done */
11131     pic16_freeAsmop(right,NULL,ic,TRUE);
11132     
11133         
11134 }
11135
11136 /*-----------------------------------------------------------------*/
11137 /* genFarPointerSet - set value from far space                     */
11138 /*-----------------------------------------------------------------*/
11139 static void genFarPointerSet (operand *right,
11140                               operand *result, iCode *ic)
11141 {
11142     int size, offset ;
11143     sym_link *retype = getSpec(operandType(right));
11144
11145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11146     pic16_aopOp(result,ic,FALSE);
11147
11148     /* if the operand is already in dptr 
11149     then we do nothing else we move the value to dptr */
11150     if (AOP_TYPE(result) != AOP_STR) {
11151         /* if this is remateriazable */
11152         if (AOP_TYPE(result) == AOP_IMMD)
11153             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11154         else { /* we need to get it byte by byte */
11155             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11156             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11157             if (options.model == MODEL_FLAT24)
11158             {
11159                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11160             }
11161         }
11162     }
11163     /* so dptr know contains the address */
11164     pic16_freeAsmop(result,NULL,ic,TRUE);
11165     pic16_aopOp(right,ic,FALSE);
11166
11167     /* if bit then unpack */
11168     if (IS_BITFIELD(retype)) 
11169         genPackBits(retype,result,right,"dptr",FPOINTER);
11170     else {
11171         size = AOP_SIZE(right);
11172         offset = 0 ;
11173
11174         while (size--) {
11175             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11176             MOVA(l);
11177             pic16_emitcode("movx","@dptr,a");
11178             if (size)
11179                 pic16_emitcode("inc","dptr");
11180         }
11181     }
11182
11183     pic16_freeAsmop(right,NULL,ic,TRUE);
11184 }
11185
11186 /*-----------------------------------------------------------------*/
11187 /* genGenPointerSet - set value from generic pointer space         */
11188 /*-----------------------------------------------------------------*/
11189 #if 0
11190 static void genGenPointerSet (operand *right,
11191                               operand *result, iCode *ic)
11192 {
11193         int i, size, offset, lit;
11194         sym_link *retype = getSpec(operandType(right));
11195
11196         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11197
11198         pic16_aopOp(result,ic,FALSE);
11199         pic16_aopOp(right,ic,FALSE);
11200         size = AOP_SIZE(right);
11201         offset = 0;
11202
11203         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11204
11205         /* if the operand is already in dptr 
11206                 then we do nothing else we move the value to dptr */
11207         if (AOP_TYPE(result) != AOP_STR) {
11208                 /* if this is remateriazable */
11209                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11210                 // WARNING: anythig until "else" is untested!
11211                 if (AOP_TYPE(result) == AOP_IMMD) {
11212                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11213                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11214                         // load FSR0 from immediate
11215                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11216                         offset = 0;
11217                         while(size--) {
11218                                 if(size) {
11219                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11220                                 } else {
11221                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11222                                 }
11223                                 offset++;
11224                         }
11225                         goto release;
11226                 }
11227                 else { /* we need to get it byte by byte */
11228                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11229                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11230
11231                         // set up FSR0 with address of result
11232                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11233                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11234
11235                         /* hack hack! see if this the FSR. If so don't load W */
11236                         if(AOP_TYPE(right) != AOP_ACC) {
11237
11238                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11239
11240                                 if(AOP_TYPE(right) == AOP_LIT)
11241                                 {
11242                                         // copy literal
11243                                         // note: pic16_popGet handles sign extension
11244                                         for(i=0;i<size;i++) {
11245                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11246                                                 if(i < size-1)
11247                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11248                                                 else
11249                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11250                                         }
11251                                 } else {
11252                                         // copy regs
11253
11254                                         for(i=0;i<size;i++) {
11255                                                 if(i < size-1)
11256                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11257                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11258                                                 else
11259                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11260                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11261                                         }
11262                                 }
11263                                 goto release;
11264                         } 
11265                         // right = ACC
11266                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11267                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11268                         goto release;
11269         } // if (AOP_TYPE(result) != AOP_IMMD)
11270
11271         } // if (AOP_TYPE(result) != AOP_STR)
11272         /* so dptr know contains the address */
11273
11274
11275         /* if bit then unpack */
11276         if (IS_BITFIELD(retype)) 
11277                 genPackBits(retype,result,right,"dptr",GPOINTER);
11278         else {
11279                 size = AOP_SIZE(right);
11280                 offset = 0 ;
11281
11282                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11283
11284                 // set up FSR0 with address of result
11285                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11286                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11287         
11288                 while (size--) {
11289                         if (AOP_TYPE(right) == AOP_LIT) {
11290                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11291                                 if (size) {
11292                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11293                                 } else {
11294                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11295                                 }
11296                         } else { // no literal
11297                                 if(size) {
11298                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11299                                 } else {
11300                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11301                                 }
11302                         }
11303                         offset++;
11304                 }
11305         }
11306
11307         release:
11308         pic16_freeAsmop(right,NULL,ic,TRUE);
11309         pic16_freeAsmop(result,NULL,ic,TRUE);
11310 }
11311 #endif
11312
11313 static void genGenPointerSet (operand *right,
11314                               operand *result, iCode *ic)
11315 {
11316   int size;
11317   sym_link *retype = getSpec(operandType(right));
11318   char fgptrput[32];
11319
11320     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11321
11322     pic16_aopOp(result,ic,FALSE);
11323     pic16_aopOp(right,ic,FALSE);
11324     size = AOP_SIZE(right);
11325
11326     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11327
11328
11329     /* if bit then unpack */
11330     if (IS_BITFIELD(retype)) {
11331 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11332       genPackBits(retype,result,right,"dptr",GPOINTER);
11333       goto release;
11334     }
11335
11336     size = AOP_SIZE(right);
11337
11338     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11339
11340
11341
11342     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11343
11344     /* value of right+0 is placed on stack, which will be retrieved
11345      * by the support function this restoring the stack. The important
11346      * thing is that there is no need to manually restore stack pointer
11347      * here */
11348     pushaop(AOP(right), 0);
11349 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11350     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11351     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11352     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11353     
11354     /* load address to write to in WREG:FSR0H:FSR0L */
11355     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11356                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11357     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11358                                 pic16_popCopyReg(&pic16_pc_prodl)));
11359     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11360     
11361
11362     /* put code here */
11363     switch (size) {
11364       case 1: strcpy(fgptrput, "__gptrput1"); break;
11365       case 2: strcpy(fgptrput, "__gptrput2"); break;
11366       case 3: strcpy(fgptrput, "__gptrput3"); break;
11367       case 4: strcpy(fgptrput, "__gptrput4"); break;
11368       default:
11369         werror(W_POSSBUG2, __FILE__, __LINE__);
11370         abort();
11371     }
11372     
11373     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11374     
11375     {
11376       symbol *sym;
11377                   
11378         sym = newSymbol( fgptrput, 0 );
11379         strcpy(sym->rname, fgptrput);
11380         checkAddSym(&externs, sym);
11381     }
11382
11383 release:
11384     pic16_freeAsmop(right,NULL,ic,TRUE);
11385     pic16_freeAsmop(result,NULL,ic,TRUE);
11386 }
11387
11388 /*-----------------------------------------------------------------*/
11389 /* genPointerSet - stores the value into a pointer location        */
11390 /*-----------------------------------------------------------------*/
11391 static void genPointerSet (iCode *ic)
11392 {    
11393     operand *right, *result ;
11394     sym_link *type, *etype;
11395     int p_type;
11396
11397     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11398
11399     right = IC_RIGHT(ic);
11400     result = IC_RESULT(ic) ;
11401
11402     /* depending on the type of pointer we need to
11403     move it to the correct pointer register */
11404     type = operandType(result);
11405     etype = getSpec(type);
11406     /* if left is of type of pointer then it is simple */
11407     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11408         p_type = DCL_TYPE(type);
11409     }
11410     else {
11411         /* we have to go by the storage class */
11412         p_type = PTR_TYPE(SPEC_OCLS(etype));
11413
11414 /*      if (SPEC_OCLS(etype)->codesp ) { */
11415 /*          p_type = CPOINTER ;  */
11416 /*      } */
11417 /*      else */
11418 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11419 /*              p_type = FPOINTER ; */
11420 /*          else */
11421 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11422 /*                  p_type = PPOINTER ; */
11423 /*              else */
11424 /*                  if (SPEC_OCLS(etype) == idata ) */
11425 /*                      p_type = IPOINTER ; */
11426 /*                  else */
11427 /*                      p_type = POINTER ; */
11428     }
11429
11430     /* now that we have the pointer type we assign
11431     the pointer values */
11432     switch (p_type) {
11433
11434     case POINTER:
11435     case IPOINTER:
11436         genNearPointerSet (right,result,ic);
11437         break;
11438
11439     case PPOINTER:
11440         genPagedPointerSet (right,result,ic);
11441         break;
11442
11443     case FPOINTER:
11444         genFarPointerSet (right,result,ic);
11445         break;
11446
11447     case GPOINTER:
11448         genGenPointerSet (right,result,ic);
11449         break;
11450
11451     default:
11452       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11453               "genPointerSet: illegal pointer type");
11454     }
11455 }
11456
11457 /*-----------------------------------------------------------------*/
11458 /* genIfx - generate code for Ifx statement                        */
11459 /*-----------------------------------------------------------------*/
11460 static void genIfx (iCode *ic, iCode *popIc)
11461 {
11462   operand *cond = IC_COND(ic);
11463   int isbit =0;
11464
11465   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11466
11467   pic16_aopOp(cond,ic,FALSE);
11468
11469   /* get the value into acc */
11470   if (AOP_TYPE(cond) != AOP_CRY)
11471     pic16_toBoolean(cond);
11472   else
11473     isbit = 1;
11474   /* the result is now in the accumulator */
11475   pic16_freeAsmop(cond,NULL,ic,TRUE);
11476
11477   /* if there was something to be popped then do it */
11478   if (popIc)
11479     genIpop(popIc);
11480
11481   /* if the condition is  a bit variable */
11482   if (isbit && IS_ITEMP(cond) && 
11483       SPIL_LOC(cond)) {
11484     genIfxJump(ic,SPIL_LOC(cond)->rname);
11485     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11486   }
11487   else {
11488     if (isbit && !IS_ITEMP(cond))
11489       genIfxJump(ic,OP_SYMBOL(cond)->rname);
11490     else
11491       genIfxJump(ic,"a");
11492   }
11493   ic->generated = 1;
11494
11495 }
11496
11497 /*-----------------------------------------------------------------*/
11498 /* genAddrOf - generates code for address of                       */
11499 /*-----------------------------------------------------------------*/
11500 static void genAddrOf (iCode *ic)
11501 {
11502   operand *result, *left;
11503   int size;
11504   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
11505   pCodeOp *pcop0, *pcop1, *pcop2;
11506
11507     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11508
11509     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
11510
11511     sym = OP_SYMBOL( IC_LEFT(ic) );
11512     
11513     if(sym->onStack) {
11514       /* get address of symbol on stack */
11515       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
11516 #if 0
11517       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
11518                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
11519 #endif
11520
11521       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11522                       pic16_popCopyReg(&pic16_pc_fsr2l),
11523                       pic16_popGet(AOP(result), 0)));
11524       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11525                       pic16_popCopyReg(&pic16_pc_fsr2h),
11526                       pic16_popGet(AOP(result), 1)));
11527       
11528       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
11529       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
11530       emitSKPNC;
11531       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
11532
11533       goto release;
11534     }
11535         
11536 //      if(pic16_debug_verbose) {
11537 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
11538 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
11539 //      }
11540         
11541     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
11542     size = AOP_SIZE(IC_RESULT(ic));
11543
11544
11545     /* Assume that what we want the address of is in data space
11546      * since there is no stack on the PIC, yet! -- VR */
11547   
11548     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11549     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11550     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11551         
11552     if (size == 3) {
11553       pic16_emitpcode(POC_MOVLW, pcop0);
11554       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11555       pic16_emitpcode(POC_MOVLW, pcop1);
11556       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11557       pic16_emitpcode(POC_MOVLW, pcop2);
11558       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11559     } else
11560     if (size == 2) {
11561       pic16_emitpcode(POC_MOVLW, pcop0);
11562       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11563       pic16_emitpcode(POC_MOVLW, pcop1);
11564     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11565     } else {
11566       pic16_emitpcode(POC_MOVLW, pcop0);
11567       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11568     }
11569
11570     pic16_freeAsmop(left, NULL, ic, FALSE);
11571 release:
11572     pic16_freeAsmop(result,NULL,ic,TRUE);
11573 }
11574
11575
11576 #if 0
11577 /*-----------------------------------------------------------------*/
11578 /* genFarFarAssign - assignment when both are in far space         */
11579 /*-----------------------------------------------------------------*/
11580 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
11581 {
11582     int size = AOP_SIZE(right);
11583     int offset = 0;
11584     char *l ;
11585     /* first push the right side on to the stack */
11586     while (size--) {
11587         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11588         MOVA(l);
11589         pic16_emitcode ("push","acc");
11590     }
11591     
11592     pic16_freeAsmop(right,NULL,ic,FALSE);
11593     /* now assign DPTR to result */
11594     pic16_aopOp(result,ic,FALSE);
11595     size = AOP_SIZE(result);
11596     while (size--) {
11597         pic16_emitcode ("pop","acc");
11598         pic16_aopPut(AOP(result),"a",--offset);
11599     }
11600     pic16_freeAsmop(result,NULL,ic,FALSE);
11601         
11602 }
11603 #endif
11604
11605 /*-----------------------------------------------------------------*/
11606 /* genAssign - generate code for assignment                        */
11607 /*-----------------------------------------------------------------*/
11608 static void genAssign (iCode *ic)
11609 {
11610   operand *result, *right;
11611   int size, offset,know_W;
11612   unsigned long lit = 0L;
11613
11614   result = IC_RESULT(ic);
11615   right  = IC_RIGHT(ic) ;
11616
11617   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11618   
11619   /* if they are the same */
11620   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11621     return ;
11622
11623   /* reversed order operands are aopOp'ed so that result operand
11624    * is effective in case right is a stack symbol. This maneauver
11625    * allows to use the _G.resDirect flag later */
11626   pic16_aopOp(result,ic,TRUE);
11627   pic16_aopOp(right,ic,FALSE);
11628
11629   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11630
11631   /* if they are the same registers */
11632   if (pic16_sameRegs(AOP(right),AOP(result)))
11633     goto release;
11634
11635   /* if the result is a bit */
11636   if (AOP_TYPE(result) == AOP_CRY) {
11637     /* if the right size is a literal then
11638        we know what the value is */
11639     if (AOP_TYPE(right) == AOP_LIT) {
11640           
11641       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11642                   pic16_popGet(AOP(result),0));
11643
11644       if (((int) operandLitValue(right))) 
11645         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11646                        AOP(result)->aopu.aop_dir,
11647                        AOP(result)->aopu.aop_dir);
11648       else
11649         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11650                        AOP(result)->aopu.aop_dir,
11651                        AOP(result)->aopu.aop_dir);
11652       goto release;
11653     }
11654
11655     /* the right is also a bit variable */
11656     if (AOP_TYPE(right) == AOP_CRY) {
11657       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11658       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11659       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11660
11661       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11662                      AOP(result)->aopu.aop_dir,
11663                      AOP(result)->aopu.aop_dir);
11664       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11665                      AOP(right)->aopu.aop_dir,
11666                      AOP(right)->aopu.aop_dir);
11667       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11668                      AOP(result)->aopu.aop_dir,
11669                      AOP(result)->aopu.aop_dir);
11670       goto release ;
11671     }
11672
11673     /* we need to or */
11674     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11675     pic16_toBoolean(right);
11676     emitSKPZ;
11677     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11678     //pic16_aopPut(AOP(result),"a",0);
11679     goto release ;
11680   }
11681
11682   /* bit variables done */
11683   /* general case */
11684   size = AOP_SIZE(result);
11685   offset = 0 ;
11686
11687   if(AOP_TYPE(right) == AOP_LIT) {
11688         if(!IS_FLOAT(operandType( right )))
11689                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11690         else {
11691            union {
11692               unsigned long lit_int;
11693               float lit_float;
11694             } info;
11695         
11696                 /* take care if literal is a float */
11697                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11698                 lit = info.lit_int;
11699         }
11700   }
11701
11702 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11703 //                      sizeof(unsigned long int), sizeof(float));
11704
11705   if(AOP_TYPE(right) != AOP_LIT
11706         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
11707         && !IS_FUNC(OP_SYM_TYPE(right))
11708         ) {
11709         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11710 //      fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11711
11712         // set up table pointer
11713         if( (AOP_TYPE(right) == AOP_PCODE)
11714                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11715 //              || (AOP(right)->aopu.pcop->type == PO_DIR)
11716                 )
11717                 )
11718         {
11719 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11720                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11721                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11722                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11723                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11724                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11725                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11726         } else {
11727 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11728                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11729                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
11730                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11731                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
11732                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11733                                 pic16_popCopyReg(&pic16_pc_tblptru)));
11734         }
11735
11736         size = min(AOP_SIZE(right), AOP_SIZE(result));
11737         while(size--) {
11738                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11739                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11740                         pic16_popGet(AOP(result),offset)));
11741                 offset++;
11742         }
11743
11744         if(AOP_SIZE(result) > AOP_SIZE(right)) {
11745                 size = AOP_SIZE(result) - AOP_SIZE(right);
11746                 while(size--) {
11747                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11748                         offset++;
11749                 }
11750         }
11751         goto release;
11752   }
11753
11754
11755
11756 #if 0
11757 /* VR - What is this?! */
11758   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
11759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11760     if(aopIdx(AOP(result),0) == 4) {
11761
11762       /* this is a workaround to save value of right into wreg too,
11763        * value of wreg is going to be used later */
11764       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11765       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11766       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11767       goto release;
11768     } else
11769 //      assert(0);
11770       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
11771   }
11772 #endif
11773
11774   know_W=-1;
11775   while (size--) {
11776   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
11777     if(AOP_TYPE(right) == AOP_LIT) {
11778       if(lit&0xff) {
11779         if(know_W != (lit&0xff))
11780           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11781         know_W = lit&0xff;
11782         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11783       } else
11784         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11785
11786       lit >>= 8;
11787
11788     } else if (AOP_TYPE(right) == AOP_CRY) {
11789       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11790       if(offset == 0) {
11791 //        debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
11792         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11793         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11794       }
11795     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11796         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11797         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11798     } else {
11799       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11800
11801       if(!_G.resDirect)         /* use this aopForSym feature */
11802         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11803     }
11804             
11805     offset++;
11806   }
11807   
11808  release:
11809   pic16_freeAsmop (right,NULL,ic,FALSE);
11810   pic16_freeAsmop (result,NULL,ic,TRUE);
11811 }   
11812
11813 /*-----------------------------------------------------------------*/
11814 /* genJumpTab - generates code for jump table                       */
11815 /*-----------------------------------------------------------------*/
11816 static void genJumpTab (iCode *ic)
11817 {
11818     symbol *jtab;
11819     char *l;
11820     pCodeOp *jt_offs;
11821     pCodeOp *jt_offs_hi;
11822     pCodeOp *jt_label;
11823
11824     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11825
11826     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11827     /* get the condition into accumulator */
11828     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11829     MOVA(l);
11830     /* multiply by three */
11831     pic16_emitcode("add","a,acc");
11832     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11833
11834     jtab = newiTempLabel(NULL);
11835     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11836     pic16_emitcode("jmp","@a+dptr");
11837     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11838
11839 #if 0
11840     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11841     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11842     emitSKPNC;
11843     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11844     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11845     pic16_emitpLabel(jtab->key);
11846
11847 #else
11848
11849     jt_offs = pic16_popGetTempReg(0);
11850     jt_offs_hi = pic16_popGetTempReg(1);
11851     jt_label = pic16_popGetLabel (jtab->key);
11852     //fprintf (stderr, "Creating jump table...\n");
11853
11854     // calculate offset into jump table (idx * sizeof (GOTO))
11855     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
11856     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
11857     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
11858     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
11859     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
11860     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
11861     pic16_emitpcode(POC_MOVWF , jt_offs);
11862
11863     // prepare PCLATx (set to first entry in jump table)
11864     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
11865     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
11866     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
11867     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
11868     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
11869
11870     // set PCLATx to selected entry (new PCL is stored in jt_offs)
11871     pic16_emitpcode(POC_ADDWF , jt_offs);
11872     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
11873     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
11874     emitSKPNC;
11875     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
11876
11877     // release temporaries and prepare jump into table (new PCL --> WREG)
11878     pic16_emitpcode(POC_MOVFW , jt_offs);
11879     pic16_popReleaseTempReg (jt_offs_hi, 1);
11880     pic16_popReleaseTempReg (jt_offs, 0);
11881
11882     // jump into the table
11883     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
11884
11885     // this goto prevents the next label from being removed...
11886     pic16_emitpcode(POC_GOTO, jt_label);
11887     pic16_emitpLabel(jtab->key);
11888
11889 #endif
11890     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11891
11892     /* now generate the jump labels */
11893     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11894          jtab = setNextItem(IC_JTLABELS(ic))) {
11895         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11896         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11897         
11898     }
11899
11900 }
11901
11902 /*-----------------------------------------------------------------*/
11903 /* genMixedOperation - gen code for operators between mixed types  */
11904 /*-----------------------------------------------------------------*/
11905 /*
11906   TSD - Written for the PIC port - but this unfortunately is buggy.
11907   This routine is good in that it is able to efficiently promote 
11908   types to different (larger) sizes. Unfortunately, the temporary
11909   variables that are optimized out by this routine are sometimes
11910   used in other places. So until I know how to really parse the 
11911   iCode tree, I'm going to not be using this routine :(.
11912 */
11913 static int genMixedOperation (iCode *ic)
11914 {
11915 #if 0
11916   operand *result = IC_RESULT(ic);
11917   sym_link *ctype = operandType(IC_LEFT(ic));
11918   operand *right = IC_RIGHT(ic);
11919   int ret = 0;
11920   int big,small;
11921   int offset;
11922
11923   iCode *nextic;
11924   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11925
11926   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11927
11928   nextic = ic->next;
11929   if(!nextic)
11930     return 0;
11931
11932   nextright = IC_RIGHT(nextic);
11933   nextleft  = IC_LEFT(nextic);
11934   nextresult = IC_RESULT(nextic);
11935
11936   pic16_aopOp(right,ic,FALSE);
11937   pic16_aopOp(result,ic,FALSE);
11938   pic16_aopOp(nextright,  nextic, FALSE);
11939   pic16_aopOp(nextleft,   nextic, FALSE);
11940   pic16_aopOp(nextresult, nextic, FALSE);
11941
11942   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11943
11944     operand *t = right;
11945     right = nextright;
11946     nextright = t; 
11947
11948     pic16_emitcode(";remove right +","");
11949
11950   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11951 /*
11952     operand *t = right;
11953     right = nextleft;
11954     nextleft = t; 
11955 */
11956     pic16_emitcode(";remove left +","");
11957   } else
11958     return 0;
11959
11960   big = AOP_SIZE(nextleft);
11961   small = AOP_SIZE(nextright);
11962
11963   switch(nextic->op) {
11964
11965   case '+':
11966     pic16_emitcode(";optimize a +","");
11967     /* if unsigned or not an integral type */
11968     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11969       pic16_emitcode(";add a bit to something","");
11970     } else {
11971
11972       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11973
11974       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11975         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11976         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11977       } else
11978         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11979
11980       offset = 0;
11981       while(--big) {
11982
11983         offset++;
11984
11985         if(--small) {
11986           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11987             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11988             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11989           }
11990
11991           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11992           emitSKPNC;
11993           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11994                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11995                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11996           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11997           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11998
11999         } else {
12000           pic16_emitcode("rlf","known_zero,w");
12001
12002           /*
12003             if right is signed
12004               btfsc  right,7
12005                addlw ff
12006           */
12007           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12008             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12009             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12010           } else {
12011             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12012           }
12013         }
12014       }
12015       ret = 1;
12016     }
12017   }
12018   ret = 1;
12019
12020 release:
12021   pic16_freeAsmop(right,NULL,ic,TRUE);
12022   pic16_freeAsmop(result,NULL,ic,TRUE);
12023   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12024   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12025   if(ret)
12026     nextic->generated = 1;
12027
12028   return ret;
12029 #else
12030   return 0;
12031 #endif
12032 }
12033 /*-----------------------------------------------------------------*/
12034 /* genCast - gen code for casting                                  */
12035 /*-----------------------------------------------------------------*/
12036 static void genCast (iCode *ic)
12037 {
12038   operand *result = IC_RESULT(ic);
12039   sym_link *ctype = operandType(IC_LEFT(ic));
12040   sym_link *rtype = operandType(IC_RIGHT(ic));
12041   operand *right = IC_RIGHT(ic);
12042   int size, offset ;
12043
12044         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12045         /* if they are equivalent then do nothing */
12046         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12047                 return ;
12048
12049         pic16_aopOp(right,ic,FALSE) ;
12050         pic16_aopOp(result,ic,FALSE);
12051
12052         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12053
12054         /* if the result is a bit */
12055         if (AOP_TYPE(result) == AOP_CRY) {
12056         
12057                 /* if the right size is a literal then
12058                  * we know what the value is */
12059                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12060
12061                 if (AOP_TYPE(right) == AOP_LIT) {
12062                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12063                                 pic16_popGet(AOP(result),0));
12064
12065                         if (((int) operandLitValue(right))) 
12066                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12067                                         AOP(result)->aopu.aop_dir,
12068                                         AOP(result)->aopu.aop_dir);
12069                         else
12070                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12071                                         AOP(result)->aopu.aop_dir,
12072                                         AOP(result)->aopu.aop_dir);
12073                         goto release;
12074                 }
12075
12076                 /* the right is also a bit variable */
12077                 if (AOP_TYPE(right) == AOP_CRY) {
12078                         emitCLRC;
12079                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12080
12081                         pic16_emitcode("clrc","");
12082                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12083                                 AOP(right)->aopu.aop_dir,
12084                                 AOP(right)->aopu.aop_dir);
12085                         pic16_aopPut(AOP(result),"c",0);
12086                         goto release ;
12087                 }
12088
12089                 /* we need to or */
12090                 if (AOP_TYPE(right) == AOP_REG) {
12091                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12092                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12093                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12094                 }
12095                 pic16_toBoolean(right);
12096                 pic16_aopPut(AOP(result),"a",0);
12097                 goto release ;
12098         }
12099
12100         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12101           int offset = 1;
12102
12103                 size = AOP_SIZE(result);
12104
12105                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12106
12107                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12108                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12109                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12110
12111                 while (size--)
12112                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12113
12114                 goto release;
12115         }
12116
12117         /* if they are the same size : or less */
12118         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12119
12120                 /* if they are in the same place */
12121                 if (pic16_sameRegs(AOP(right),AOP(result)))
12122                         goto release;
12123
12124                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12125 #if 0
12126                 if (IS_PTR_CONST(rtype))
12127 #else
12128                 if (IS_CODEPTR(rtype))
12129 #endif
12130                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12131
12132 #if 0
12133                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12134 #else
12135                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12136 #endif
12137                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12138
12139 #if 0
12140                 if(AOP_TYPE(right) == AOP_IMMD) {
12141                   pCodeOp *pcop0, *pcop1, *pcop2;
12142                   symbol *sym = OP_SYMBOL( right );
12143
12144                         size = AOP_SIZE(result);
12145                         /* low */
12146                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12147                         /* high */
12148                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12149                         /* upper */
12150                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12151         
12152                         if (size == 3) {
12153                                 pic16_emitpcode(POC_MOVLW, pcop0);
12154                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12155                                 pic16_emitpcode(POC_MOVLW, pcop1);
12156                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12157                                 pic16_emitpcode(POC_MOVLW, pcop2);
12158                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12159                         } else
12160                         if (size == 2) {
12161                                 pic16_emitpcode(POC_MOVLW, pcop0);
12162                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12163                                 pic16_emitpcode(POC_MOVLW, pcop1);
12164                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12165                         } else {
12166                                 pic16_emitpcode(POC_MOVLW, pcop0);
12167                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12168                         }
12169                 } else
12170 #endif
12171                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12172                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12173                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12174                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12175                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12176                         if(AOP_SIZE(result) <2)
12177                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12178                 } else {
12179                         /* if they in different places then copy */
12180                         size = AOP_SIZE(result);
12181                         offset = 0 ;
12182                         while (size--) {
12183                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12184                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12185                                 offset++;
12186                         }
12187                 }
12188                 goto release;
12189         }
12190
12191         /* if the result is of type pointer */
12192         if (IS_PTR(ctype)) {
12193           int p_type;
12194           sym_link *type = operandType(right);
12195           sym_link *etype = getSpec(type);
12196
12197                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12198
12199                 /* pointer to generic pointer */
12200                 if (IS_GENPTR(ctype)) {
12201                   char *l = zero;
12202             
12203                         if (IS_PTR(type)) 
12204                                 p_type = DCL_TYPE(type);
12205                         else {
12206                 /* we have to go by the storage class */
12207                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12208
12209 /*              if (SPEC_OCLS(etype)->codesp )  */
12210 /*                  p_type = CPOINTER ;  */
12211 /*              else */
12212 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12213 /*                      p_type = FPOINTER ; */
12214 /*                  else */
12215 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12216 /*                          p_type = PPOINTER; */
12217 /*                      else */
12218 /*                          if (SPEC_OCLS(etype) == idata ) */
12219 /*                              p_type = IPOINTER ; */
12220 /*                          else */
12221 /*                              p_type = POINTER ; */
12222             }
12223                 
12224             /* the first two bytes are known */
12225       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12226             size = GPTRSIZE - 1; 
12227             offset = 0 ;
12228             while (size--) {
12229               if(offset < AOP_SIZE(right)) {
12230                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12231                 mov2f(AOP(result), AOP(right), offset);
12232 /*
12233                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12234                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12235                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12236                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12237                 } else { 
12238                   
12239                   pic16_aopPut(AOP(result),
12240                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12241                          offset);
12242                 }
12243 */
12244               } else 
12245                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12246               offset++;
12247             }
12248             /* the last byte depending on type */
12249             switch (p_type) {
12250             case IPOINTER:
12251             case POINTER:
12252                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12253                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12254 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12255                 break;
12256
12257             case CPOINTER:
12258                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12259                 break;
12260
12261             case FPOINTER:
12262               pic16_emitcode(";BUG!? ","%d",__LINE__);
12263                 l = one;
12264                 break;
12265             case PPOINTER:
12266               pic16_emitcode(";BUG!? ","%d",__LINE__);
12267                 l = "#0x03";
12268                 break;
12269
12270             case GPOINTER:
12271               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12272               break;
12273               
12274             default:
12275                 /* this should never happen */
12276                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12277                        "got unknown pointer type");
12278                 exit(1);
12279             }
12280             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12281             goto release ;
12282         }
12283         
12284         /* just copy the pointers */
12285         size = AOP_SIZE(result);
12286         offset = 0 ;
12287         while (size--) {
12288             pic16_aopPut(AOP(result),
12289                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12290                    offset);
12291             offset++;
12292         }
12293         goto release ;
12294     }
12295     
12296
12297
12298     /* so we now know that the size of destination is greater
12299     than the size of the source.
12300     Now, if the next iCode is an operator then we might be
12301     able to optimize the operation without performing a cast.
12302     */
12303     if(genMixedOperation(ic))
12304       goto release;
12305
12306     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12307     
12308     /* we move to result for the size of source */
12309     size = AOP_SIZE(right);
12310     offset = 0 ;
12311     while (size--) {
12312       mov2f(AOP(result), AOP(right), offset);
12313       offset++;
12314     }
12315
12316     /* now depending on the sign of the destination */
12317     size = AOP_SIZE(result) - AOP_SIZE(right);
12318     /* if unsigned or not an integral type */
12319     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12320       while (size--)
12321         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12322     } else {
12323       /* we need to extend the sign :( */
12324
12325       if(size == 1) {
12326         /* Save one instruction of casting char to int */
12327         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12328         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12329         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12330       } else {
12331         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12332
12333         if(offset)
12334           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12335         else
12336           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12337         
12338         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12339
12340         while (size--)
12341           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12342       }
12343     }
12344
12345 release:
12346     pic16_freeAsmop(right,NULL,ic,TRUE);
12347     pic16_freeAsmop(result,NULL,ic,TRUE);
12348
12349 }
12350
12351 /*-----------------------------------------------------------------*/
12352 /* genDjnz - generate decrement & jump if not zero instrucion      */
12353 /*-----------------------------------------------------------------*/
12354 static int genDjnz (iCode *ic, iCode *ifx)
12355 {
12356     symbol *lbl, *lbl1;
12357     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12358
12359     if (!ifx)
12360         return 0;
12361     
12362     /* if the if condition has a false label
12363        then we cannot save */
12364     if (IC_FALSE(ifx))
12365         return 0;
12366
12367     /* if the minus is not of the form 
12368        a = a - 1 */
12369     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12370         !IS_OP_LITERAL(IC_RIGHT(ic)))
12371         return 0;
12372
12373     if (operandLitValue(IC_RIGHT(ic)) != 1)
12374         return 0;
12375
12376     /* if the size of this greater than one then no
12377        saving */
12378     if (getSize(operandType(IC_RESULT(ic))) > 1)
12379         return 0;
12380
12381     /* otherwise we can save BIG */
12382     lbl = newiTempLabel(NULL);
12383     lbl1= newiTempLabel(NULL);
12384
12385     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12386     
12387     if (IS_AOP_PREG(IC_RESULT(ic))) {
12388         pic16_emitcode("dec","%s",
12389                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12390         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12391         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12392     } else {    
12393
12394
12395       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12396       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12397
12398       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12399       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12400
12401     }
12402     
12403     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12404     ifx->generated = 1;
12405     return 1;
12406 }
12407
12408 /*-----------------------------------------------------------------*/
12409 /* genReceive - generate code for a receive iCode                  */
12410 /*-----------------------------------------------------------------*/
12411 static void genReceive (iCode *ic)
12412 {    
12413   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12414
12415 #if 0
12416   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12417         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12418 #endif
12419 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12420
12421   if (isOperandInFarSpace(IC_RESULT(ic))
12422       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12423           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12424
12425     int size = getSize(operandType(IC_RESULT(ic)));
12426     int offset =  pic16_fReturnSizePic - size;
12427
12428       assert( 0 );
12429       while (size--) {
12430         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12431                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12432                       offset++;
12433         }
12434
12435       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12436
12437       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12438       size = AOP_SIZE(IC_RESULT(ic));
12439       offset = 0;
12440       while (size--) {
12441         pic16_emitcode ("pop","acc");
12442         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12443       }
12444   } else {
12445     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12446
12447     _G.accInUse++;
12448     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12449     _G.accInUse--;
12450     assignResultValue(IC_RESULT(ic), 0);
12451   }
12452
12453   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12454 }
12455
12456 /*-----------------------------------------------------------------*/
12457 /* genDummyRead - generate code for dummy read of volatiles        */
12458 /*-----------------------------------------------------------------*/
12459 static void
12460 genDummyRead (iCode * ic)
12461 {
12462   pic16_emitcode ("; genDummyRead","");
12463   pic16_emitcode ("; not implemented","");
12464
12465   ic = ic;
12466 }
12467
12468 /*-----------------------------------------------------------------*/
12469 /* genpic16Code - generate code for pic16 based controllers        */
12470 /*-----------------------------------------------------------------*/
12471 /*
12472  * At this point, ralloc.c has gone through the iCode and attempted
12473  * to optimize in a way suitable for a PIC. Now we've got to generate
12474  * PIC instructions that correspond to the iCode.
12475  *
12476  * Once the instructions are generated, we'll pass through both the
12477  * peep hole optimizer and the pCode optimizer.
12478  *-----------------------------------------------------------------*/
12479
12480 void genpic16Code (iCode *lic)
12481 {
12482     iCode *ic;
12483     int cln = 0;
12484
12485     lineHead = lineCurr = NULL;
12486
12487     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12488     pic16_addpBlock(pb);
12489
12490 #if 0
12491     /* if debug information required */
12492     if (options.debug && currFunc) {
12493       if (currFunc) {
12494         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12495       }
12496     }
12497 #endif
12498
12499     for (ic = lic ; ic ; ic = ic->next ) {
12500
12501       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
12502         if ( cln != ic->lineno ) {
12503             if ( options.debug ) {
12504               debugFile->writeCLine (ic);
12505             }
12506             
12507             if(!options.noCcodeInAsm) {
12508                 pic16_addpCode2pBlock(pb,
12509                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
12510                                 printCLine(ic->filename, ic->lineno)));
12511             }
12512
12513             cln = ic->lineno ;
12514         }
12515         
12516         if(options.iCodeInAsm) {
12517                 char *l;
12518                 /* insert here code to print iCode as comment */
12519                 l = Safe_strdup(printILine(ic));
12520                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
12521         }
12522         
12523         /* if the result is marked as
12524            spilt and rematerializable or code for
12525            this has already been generated then
12526            do nothing */
12527         if (resultRemat(ic) || ic->generated ) 
12528             continue ;
12529         
12530         /* depending on the operation */
12531         switch (ic->op) {
12532         case '!' :
12533             pic16_genNot(ic);
12534             break;
12535             
12536         case '~' :
12537             pic16_genCpl(ic);
12538             break;
12539             
12540         case UNARYMINUS:
12541             genUminus (ic);
12542             break;
12543             
12544         case IPUSH:
12545             genIpush (ic);
12546             break;
12547             
12548         case IPOP:
12549             /* IPOP happens only when trying to restore a 
12550                spilt live range, if there is an ifx statement
12551                following this pop then the if statement might
12552                be using some of the registers being popped which
12553                would destroy the contents of the register so
12554                we need to check for this condition and handle it */
12555             if (ic->next            && 
12556                 ic->next->op == IFX &&
12557                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
12558                 genIfx (ic->next,ic);
12559             else
12560                 genIpop (ic);
12561             break; 
12562             
12563         case CALL:
12564             genCall (ic);
12565             break;
12566             
12567         case PCALL:
12568             genPcall (ic);
12569             break;
12570             
12571         case FUNCTION:
12572             genFunction (ic);
12573             break;
12574             
12575         case ENDFUNCTION:
12576             genEndFunction (ic);
12577             break;
12578             
12579         case RETURN:
12580             genRet (ic);
12581             break;
12582             
12583         case LABEL:
12584             genLabel (ic);
12585             break;
12586             
12587         case GOTO:
12588             genGoto (ic);
12589             break;
12590             
12591         case '+' :
12592             pic16_genPlus (ic) ;
12593             break;
12594             
12595         case '-' :
12596             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
12597                 pic16_genMinus (ic);
12598             break;
12599             
12600         case '*' :
12601             genMult (ic);
12602             break;
12603             
12604         case '/' :
12605             genDiv (ic) ;
12606             break;
12607             
12608         case '%' :
12609             genMod (ic);
12610             break;
12611             
12612         case '>' :
12613             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
12614             break;
12615             
12616         case '<' :
12617             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
12618             break;
12619             
12620         case LE_OP:
12621         case GE_OP:
12622         case NE_OP:
12623             
12624             /* note these two are xlated by algebraic equivalence
12625                during parsing SDCC.y */
12626             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12627                    "got '>=' or '<=' shouldn't have come here");
12628             break;      
12629             
12630         case EQ_OP:
12631             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
12632             break;          
12633             
12634         case AND_OP:
12635             genAndOp (ic);
12636             break;
12637             
12638         case OR_OP:
12639             genOrOp (ic);
12640             break;
12641             
12642         case '^' :
12643             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12644             break;
12645             
12646         case '|' :
12647                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12648             break;
12649             
12650         case BITWISEAND:
12651             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12652             break;
12653             
12654         case INLINEASM:
12655             genInline (ic);
12656             break;
12657             
12658         case RRC:
12659             genRRC (ic);
12660             break;
12661             
12662         case RLC:
12663             genRLC (ic);
12664             break;
12665             
12666         case GETHBIT:
12667             genGetHbit (ic);
12668             break;
12669             
12670         case LEFT_OP:
12671             genLeftShift (ic);
12672             break;
12673             
12674         case RIGHT_OP:
12675             genRightShift (ic);
12676             break;
12677             
12678         case GET_VALUE_AT_ADDRESS:
12679             genPointerGet(ic);
12680             break;
12681             
12682         case '=' :
12683             if (POINTER_SET(ic))
12684                 genPointerSet(ic);
12685             else
12686                 genAssign(ic);
12687             break;
12688             
12689         case IFX:
12690             genIfx (ic,NULL);
12691             break;
12692             
12693         case ADDRESS_OF:
12694             genAddrOf (ic);
12695             break;
12696             
12697         case JUMPTABLE:
12698             genJumpTab (ic);
12699             break;
12700             
12701         case CAST:
12702             genCast (ic);
12703             break;
12704             
12705         case RECEIVE:
12706             genReceive(ic);
12707             break;
12708             
12709         case SEND:
12710             addSet(&_G.sendSet,ic);
12711             /* create a reversed list of SEND iCodes */
12712 //            addSetHead(&_G.sendSet, ic);
12713             break;
12714
12715         case DUMMY_READ_VOLATILE:
12716           genDummyRead (ic);
12717           break;
12718
12719         default :
12720             ic = ic;
12721         }
12722     }
12723
12724
12725     /* now we are ready to call the
12726        peep hole optimizer */
12727     if (!options.nopeep) {
12728       peepHole (&lineHead);
12729     }
12730     /* now do the actual printing */
12731     printLine (lineHead, codeOutFile);
12732
12733 #ifdef PCODE_DEBUG
12734     DFPRINTF((stderr,"printing pBlock\n\n"));
12735     pic16_printpBlock(stdout,pb);
12736 #endif
12737
12738     return;
12739 }
12740