* src/pic16/pcode.c (assignToSameBank) : fixed cast to pointer of
[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,2005)
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 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int usefastretfie;
157     bitVect *fregsUsed;
158     int stack_lat;                      /* stack offset latency */
159     int resDirect;
160     int useWreg;                        /* flag when WREG is used to pass function parameter */
161 } _G;
162
163 /* Resolved ifx structure. This structure stores information
164    about an iCode ifx that makes it easier to generate code.
165 */
166 typedef struct resolvedIfx {
167   symbol *lbl;     /* pointer to a label */
168   int condition;   /* true or false ifx */
169   int generated;   /* set true when the code associated with the ifx
170                     * is generated */
171 } resolvedIfx;
172
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
177
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
180
181 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
185
186 static  pBlock *pb;
187
188 /*-----------------------------------------------------------------*/
189 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
190 /*                 exponent of 2 is returned, otherwise -1 is      */
191 /*                 returned.                                       */
192 /* note that this is similar to the function `powof2' in SDCCsymt  */
193 /* if(n == 2^y)                                                    */
194 /*   return y;                                                     */
195 /* return -1;                                                      */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
198 {
199   if(num) {
200     if( (num & (num-1)) == 0) {
201       int nshifts = -1;
202       while(num) {
203         num>>=1;
204         nshifts++;
205       }
206       return nshifts;
207     }
208   }
209
210   return -1;
211 }
212
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
214 {
215   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
216                        line_no,
217                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
220                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
222                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223                        ((result) ? AOP_SIZE(result) : 0));
224 }
225
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
227 {
228
229   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
230                        line_no,
231                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
234                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
235                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
236                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
237
238 }
239
240 void pic16_emitpcomment (char *fmt, ...)
241 {
242     va_list ap;
243     char lb[INITIAL_INLINEASM];  
244     char *lbp = lb;
245
246     va_start(ap,fmt);   
247
248     lb[0] = ';';
249     vsprintf(lb+1,fmt,ap);
250
251     while (isspace(*lbp)) lbp++;
252
253     if (lbp && *lbp) 
254         lineCurr = (lineCurr ?
255                     connectLine(lineCurr,newLineNode(lb)) :
256                     (lineHead = newLineNode(lb)));
257     lineCurr->isInline = _G.inLine;
258     lineCurr->isDebug  = _G.debugLine;
259
260     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
261     va_end(ap);
262
263 //      fprintf(stderr, "%s\n", lb);
264 }
265
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
267 {
268     va_list ap;
269     char lb[INITIAL_INLINEASM];  
270     char *lbp = lb;
271
272     if(!pic16_debug_verbose)
273       return;
274
275     va_start(ap,fmt);   
276
277     if (inst && *inst) {
278         if (fmt && *fmt)
279             sprintf(lb,"%s\t",inst);
280         else
281             sprintf(lb,"%s",inst);
282         vsprintf(lb+(strlen(lb)),fmt,ap);
283     }  else
284         vsprintf(lb,fmt,ap);
285
286     while (isspace(*lbp)) lbp++;
287
288     if (lbp && *lbp) 
289         lineCurr = (lineCurr ?
290                     connectLine(lineCurr,newLineNode(lb)) :
291                     (lineHead = newLineNode(lb)));
292     lineCurr->isInline = _G.inLine;
293     lineCurr->isDebug  = _G.debugLine;
294
295     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
296     va_end(ap);
297
298 //      fprintf(stderr, "%s\n", lb);
299 }
300
301
302
303 void pic16_emitpLabel(int key)
304 {
305   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
306 }
307
308 void pic16_emitpLabelFORCE(int key)
309 {
310   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
311 }
312
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
314 {
315
316   if(pcop)
317     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
318   else
319     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
320 }
321
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
323 {
324   if(pcop)
325     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
326   else
327     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
328 }
329   
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
331 {
332
333   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334
335 }
336
337
338 #if 1
339 #define pic16_emitcode  DEBUGpic16_emitcode
340 #else
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple    */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
345 {
346     va_list ap;
347     char lb[INITIAL_INLINEASM];  
348     char *lbp = lb;
349
350     va_start(ap,fmt);   
351
352     if (inst && *inst) {
353         if (fmt && *fmt)
354             sprintf(lb,"%s\t",inst);
355         else
356             sprintf(lb,"%s",inst);
357         vsprintf(lb+(strlen(lb)),fmt,ap);
358     }  else
359         vsprintf(lb,fmt,ap);
360
361     while (isspace(*lbp)) lbp++;
362
363     if (lbp && *lbp) 
364         lineCurr = (lineCurr ?
365                     connectLine(lineCurr,newLineNode(lb)) :
366                     (lineHead = newLineNode(lb)));
367     lineCurr->isInline = _G.inLine;
368     lineCurr->isDebug  = _G.debugLine;
369
370 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
371
372 //    if(pic16_debug_verbose)
373 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
374
375     va_end(ap);
376 }
377 #endif
378
379
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location  */
382 /*   with a debugger symbol                                        */
383 /*-----------------------------------------------------------------*/
384 void
385 pic16_emitDebuggerSymbol (char * debugSym)
386 {
387   _G.debugLine = 1;
388   pic16_emitcode (";", "%s ==.", debugSym);
389   _G.debugLine = 0;
390 }
391
392
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
397 {
398 //    bool r0iu = FALSE , r1iu = FALSE;
399 //    bool r0ou = FALSE , r1ou = FALSE;
400     bool fsr0iu = FALSE, fsr0ou;
401     bool fsr2iu = FALSE, fsr2ou;
402     
403     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
404
405     
406     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
408     
409     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
411
412     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
415     }
416
417     if(!fsr0iu && !fsr0ou) {
418         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419         (*aopp)->type = AOP_FSR0;
420
421         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
422         
423       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
424     }
425
426 #if 0
427     /* no usage of FSR2 */
428     if(!fsr2iu && !fsr2ou) {
429         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430         (*aopp)->type = AOP_FSR2;
431
432       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
433     }
434 #endif
435         
436     /* now we know they both have usage */
437     /* if fsr0 not used in this instruction */
438     if (!fsr0iu) {
439         if (!_G.fsr0Pushed) {
440                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
442                 _G.fsr0Pushed++;
443         }
444
445         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446         (*aopp)->type = AOP_FSR0;
447
448 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
449
450       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
451     }
452         
453
454     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
455     assert( 0 );
456
457     return NULL;
458 #if 0
459     /* the logic: if r0 & r1 used in the instruction
460     then we are in trouble otherwise */
461
462     /* first check if r0 & r1 are used by this
463     instruction, in which case we are in trouble */
464     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
466     {
467         goto endOfWorld;      
468     }
469
470     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
472
473     /* if no usage of r0 then return it */
474     if (!r0iu && !r0ou) {
475         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476         (*aopp)->type = AOP_R0; 
477         
478         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
479     }
480
481     /* if no usage of r1 then return it */
482     if (!r1iu && !r1ou) {
483         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484         (*aopp)->type = AOP_R1;
485
486         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
487     }    
488
489     /* now we know they both have usage */
490     /* if r0 not used in this instruction */
491     if (!r0iu) {
492         /* push it if not already pushed */
493         if (!_G.r0Pushed) {
494           //pic16_emitcode ("push","%s",
495           //          pic16_regWithIdx(R0_IDX)->dname);
496             _G.r0Pushed++ ;
497         }
498         
499         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500         (*aopp)->type = AOP_R0;
501
502         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
503     }
504
505     /* if r1 not used then */
506
507     if (!r1iu) {
508         /* push it if not already pushed */
509         if (!_G.r1Pushed) {
510           //pic16_emitcode ("push","%s",
511           //          pic16_regWithIdx(R1_IDX)->dname);
512             _G.r1Pushed++ ;
513         }
514         
515         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516         (*aopp)->type = AOP_R1;
517         return pic16_regWithIdx(R1_IDX);
518     }
519
520 endOfWorld :
521     /* I said end of world but not quite end of world yet */
522     /* if this is a result then we can push it on the stack*/
523     if (result) {
524         (*aopp)->type = AOP_STK;    
525         return NULL;
526     }
527
528     /* other wise this is true end of the world */
529     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530            "getFreePtr should never reach here");
531     exit(0);
532 #endif
533 }
534
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp                                  */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
539 {
540     asmop *aop;
541
542     aop = Safe_calloc(1,sizeof(asmop));
543     aop->type = type;
544     return aop;
545 }
546
547 static void genSetDPTR(int n)
548 {
549     if (!n)
550     {
551         pic16_emitcode(";", "Select standard DPTR");
552         pic16_emitcode("mov", "dps, #0x00");
553     }
554     else
555     {
556         pic16_emitcode(";", "Select alternate DPTR");
557         pic16_emitcode("mov", "dps, #0x01");
558     }
559 }
560
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for  */
563 /*              generating code                                    */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
566 {
567   FENTRY2;
568   
569 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570
571   if(!resIfx) 
572     return;
573
574
575   resIfx->condition = 1;    /* assume that the ifx is true */
576   resIfx->generated = 0;    /* indicate that the ifx has not been used */
577
578   if(!ifx) {
579     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
580
581 #if 1
582     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583                         __FUNCTION__,__LINE__,resIfx->lbl->key);
584 #endif
585
586   } else {
587     if(IC_TRUE(ifx)) {
588       resIfx->lbl = IC_TRUE(ifx);
589     } else {
590       resIfx->lbl = IC_FALSE(ifx);
591       resIfx->condition = 0;
592     }
593
594 #if 1
595     if(IC_TRUE(ifx)) 
596       DEBUGpic16_emitcode("; +++","ifx true is non-null");
597     else
598       DEBUGpic16_emitcode("; +++","ifx true is null");
599     if(IC_FALSE(ifx)) 
600       DEBUGpic16_emitcode("; +++","ifx false is non-null");
601     else
602       DEBUGpic16_emitcode("; +++","ifx false is null");
603 #endif
604   }
605
606   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
607
608 }
609 #if 0
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type               */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
614 {
615
616     return PTR_TYPE(SPEC_OCLS(etype));
617
618 }
619 #endif
620
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol                                   */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
625 {
626     symbol *sym=OP_SYMBOL(op);
627     asmop *aop;
628     memmap *space= SPEC_OCLS(sym->etype);
629
630     FENTRY2;
631     
632     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
633     
634 //    sym = OP_SYMBOL(op);
635
636     /* if already has one */
637     if (sym->aop) {
638             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
639         return sym->aop;
640     }
641
642 #if 0
643     /* if symbol was initially placed onStack then we must re-place it
644      * to direct memory, since pic16 does not have a specific stack */
645     if(sym->onStack) {
646         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
647     }
648 #endif
649
650
651 #if 0
652     if(sym->iaccess) {
653       if(space->paged) {
654         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
655
656         sym->aop = aop = newAsmop (AOP_PAGED);
657         aop->aopu.aop_dir = sym->rname ;
658         aop->size = getSize(sym->type);
659         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660         pic16_allocDirReg( IC_LEFT(ic) );
661         return aop;
662       }
663       assert( 0 );
664     }
665 #endif
666     
667 #if 1
668     /* assign depending on the storage class */
669     /* if it is on the stack or indirectly addressable */
670     /* space we need to assign either r0 or r1 to it   */    
671     if (sym->onStack)   // || sym->iaccess)
672     {
673       pCodeOp *pcop[4];
674       int i;
675       
676         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
678         
679         /* acquire a temporary register -- it is saved in function */
680
681         sym->aop = aop = newAsmop(AOP_STA);
682         aop->aopu.stk.stk = sym->stack;
683         aop->size = getSize(sym->type);
684
685
686         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
690           
691           for(i=0;i<aop->size;i++)
692             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
694         } else
695           for(i=0;i<aop->size;i++) {
696             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
698           }
699
700
701 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
702
703 #if 1
704         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
705         
706         if(_G.accInUse) {
707                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
708         }
709         
710         for(i=0;i<aop->size;i++) {
711
712           /* initialise for stack access via frame pointer */
713           // operands on stack are accessible via "FSR2 + index" with index
714           // starting at 2 for arguments and growing from 0 downwards for
715           // local variables (index == 0 is not assigned so we add one here)
716           {
717             int soffs = sym->stack;
718             if (soffs <= 0) {
719               assert (soffs < 0);
720               soffs++;
721             } // if
722             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
723             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
724                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
725           }
726         }
727         
728         if(_G.accInUse) {
729                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730         }
731         
732         return (aop);
733 #endif
734
735 #if 0
736         /* now assign the address of the variable to 
737         the pointer register */
738         if (aop->type != AOP_STK) {
739
740             if (sym->onStack) {
741                     if ( _G.accInUse )
742                         pic16_emitcode("push","acc");
743
744                     pic16_emitcode("mov","a,_bp");
745                     pic16_emitcode("add","a,#0x%02x",
746                              ((sym->stack < 0) ?
747                               ((char)(sym->stack - _G.nRegsSaved )) :
748                               ((char)sym->stack)) & 0xff);
749                     pic16_emitcode("mov","%s,a",
750                              aop->aopu.aop_ptr->name);
751
752                     if ( _G.accInUse )
753                         pic16_emitcode("pop","acc");
754             } else
755                 pic16_emitcode("mov","%s,#%s",
756                          aop->aopu.aop_ptr->name,
757                          sym->rname);
758             aop->paged = space->paged;
759         } else
760             aop->aopu.aop_stk = sym->stack;
761         return aop;
762 #endif
763
764     }
765 #endif
766
767 #if 0
768     if (sym->onStack && options.stack10bit)
769     {
770         /* It's on the 10 bit stack, which is located in
771          * far data space.
772          */
773          
774       //DEBUGpic16_emitcode(";","%d",__LINE__);
775
776         if ( _G.accInUse )
777                 pic16_emitcode("push","acc");
778
779         pic16_emitcode("mov","a,_bp");
780         pic16_emitcode("add","a,#0x%02x",
781                  ((sym->stack < 0) ?
782                    ((char)(sym->stack - _G.nRegsSaved )) :
783                    ((char)sym->stack)) & 0xff);
784         
785         genSetDPTR(1);
786         pic16_emitcode ("mov","dpx1,#0x40");
787         pic16_emitcode ("mov","dph1,#0x00");
788         pic16_emitcode ("mov","dpl1, a");
789         genSetDPTR(0);
790         
791         if ( _G.accInUse )
792             pic16_emitcode("pop","acc");
793             
794         sym->aop = aop = newAsmop(AOP_DPTR2);
795         aop->size = getSize(sym->type); 
796         return aop;
797     }
798 #endif
799
800 #if 1
801     /* special case for a function */
802     if (IS_FUNC(sym->type)) {   
803         sym->aop = aop = newAsmop(AOP_PCODE);
804         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
805         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
806         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
807         PCOI(aop->aopu.pcop)->index = 0;
808         aop->size = FPTRSIZE; 
809         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
810         return aop;
811     }
812 #endif
813
814
815
816     //DEBUGpic16_emitcode(";","%d",__LINE__);
817     /* if in bit space */
818     if (IN_BITSPACE(space)) {
819         sym->aop = aop = newAsmop (AOP_CRY);
820         aop->aopu.aop_dir = sym->rname ;
821         aop->size = getSize(sym->type);
822         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
823         return aop;
824     }
825     /* if it is in direct space */
826     if (IN_DIRSPACE(space)) {
827         sym->aop = aop = newAsmop (AOP_DIR);
828         aop->aopu.aop_dir = sym->rname ;
829         aop->size = getSize(sym->type);
830         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
831         pic16_allocDirReg( IC_LEFT(ic) );
832         return aop;
833     }
834
835
836     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
837         sym->aop = aop = newAsmop (AOP_DIR);
838         aop->aopu.aop_dir = sym->rname ;
839         aop->size = getSize(sym->type);
840         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841         pic16_allocDirReg( IC_LEFT(ic) );
842         return aop;
843     }
844
845
846     /* only remaining is far space */
847     sym->aop = aop = newAsmop(AOP_PCODE);
848
849 /* change the next if to 1 to revert to good old immediate code */
850         if(IN_CODESPACE(space)) {
851                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
852                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
853                 PCOI(aop->aopu.pcop)->index = 0;
854         } else {
855                 /* try to allocate via direct register */
856                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
857 //              aop->size = getSize( sym->type );
858         }
859
860         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
861                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
862
863 #if 0
864         if(!pic16_allocDirReg (IC_LEFT(ic)))
865                 return NULL;
866 #endif
867
868         if(IN_DIRSPACE( space ))
869                 aop->size = PTRSIZE;
870         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
871                 aop->size = FPTRSIZE;
872         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
873         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
874         else if(sym->onStack) {
875                 aop->size = PTRSIZE;
876         } else {
877           if(SPEC_SCLS(sym->etype) == S_PDATA) {
878             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
879             aop->size = FPTRSIZE;
880           } else
881                 assert( 0 );
882         }
883
884     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
885
886     /* if it is in code space */
887     if (IN_CODESPACE(space))
888         aop->code = 1;
889
890     return aop;     
891 }
892
893 /*-----------------------------------------------------------------*/
894 /* aopForRemat - rematerialzes an object                           */
895 /*-----------------------------------------------------------------*/
896 static asmop *aopForRemat (operand *op) // x symbol *sym)
897 {
898   symbol *sym = OP_SYMBOL(op);
899   operand *refop;
900   iCode *ic = NULL, *oldic;
901   asmop *aop = newAsmop(AOP_PCODE);
902   int val = 0;
903   int offset = 0;
904   int viaimmd=0;
905
906     FENTRY2;
907     
908         ic = sym->rematiCode;
909
910         if(IS_OP_POINTER(op)) {
911                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
912         }
913
914         for (;;) {
915                 oldic = ic;
916
917 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
918         
919                 if (ic->op == '+') {
920                         val += (int) operandLitValue(IC_RIGHT(ic));
921                 } else if (ic->op == '-') {
922                         val -= (int) operandLitValue(IC_RIGHT(ic));
923                 } else
924                         break;
925                 
926                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
927         }
928
929         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
930         refop = IC_LEFT(ic);
931
932         if(!op->isaddr)viaimmd++; else viaimmd=0;
933                 
934 /* set the following if to 1 to revert to good old immediate code */
935         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
936                 || viaimmd) {
937
938                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
939
940                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
941
942 #if 0
943                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
944 #else
945                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
946 #endif
947
948                 PCOI(aop->aopu.pcop)->index = val;
949                 
950                 aop->size = getSize( sym->type );
951         } else {
952                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
953
954                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
955                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
956
957                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
958         }
959
960
961         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
962                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
963 #if 0
964                 val, IS_PTR_CONST(operandType(op)));
965 #else
966                 val, IS_CODEPTR(operandType(op)));
967 #endif
968
969 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
970
971         pic16_allocDirReg (IC_LEFT(ic));
972
973         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
974                 aop->code = 1;
975
976   return aop;        
977 }
978
979 #if 0
980 static int aopIdx (asmop *aop, int offset)
981 {
982   if(!aop)
983     return -1;
984
985   if(aop->type !=  AOP_REG)
986     return -2;
987         
988   return aop->aopu.aop_reg[offset]->rIdx;
989
990 }
991 #endif
992
993 /*-----------------------------------------------------------------*/
994 /* regsInCommon - two operands have some registers in common       */
995 /*-----------------------------------------------------------------*/
996 static bool regsInCommon (operand *op1, operand *op2)
997 {
998     symbol *sym1, *sym2;
999     int i;
1000
1001     /* if they have registers in common */
1002     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1003         return FALSE ;
1004
1005     sym1 = OP_SYMBOL(op1);
1006     sym2 = OP_SYMBOL(op2);
1007
1008     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1009         return FALSE ;
1010
1011     for (i = 0 ; i < sym1->nRegs ; i++) {
1012         int j;
1013         if (!sym1->regs[i])
1014             continue ;
1015
1016         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1017             if (!sym2->regs[j])
1018                 continue ;
1019
1020             if (sym2->regs[j] == sym1->regs[i])
1021                 return TRUE ;
1022         }
1023     }
1024
1025     return FALSE ;
1026 }
1027
1028 /*-----------------------------------------------------------------*/
1029 /* operandsEqu - equivalent                                        */
1030 /*-----------------------------------------------------------------*/
1031 static bool operandsEqu ( operand *op1, operand *op2)
1032 {
1033     symbol *sym1, *sym2;
1034
1035     /* if they not symbols */
1036     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1037         return FALSE;
1038
1039     sym1 = OP_SYMBOL(op1);
1040     sym2 = OP_SYMBOL(op2);
1041
1042     /* if both are itemps & one is spilt
1043        and the other is not then false */
1044     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1045         sym1->isspilt != sym2->isspilt )
1046         return FALSE ;
1047
1048     /* if they are the same */
1049     if (sym1 == sym2)
1050         return TRUE ;
1051
1052     if (sym1->rname[0] && sym2->rname[0]
1053         && strcmp (sym1->rname, sym2->rname) == 0)
1054         return TRUE;
1055
1056
1057     /* if left is a tmp & right is not */
1058     if (IS_ITEMP(op1)  && 
1059         !IS_ITEMP(op2) &&
1060         sym1->isspilt  &&
1061         (sym1->usl.spillLoc == sym2))
1062         return TRUE;
1063
1064     if (IS_ITEMP(op2)  && 
1065         !IS_ITEMP(op1) &&
1066         sym2->isspilt  &&
1067         sym1->level > 0 &&
1068         (sym2->usl.spillLoc == sym1))
1069         return TRUE ;
1070
1071     return FALSE ;
1072 }
1073
1074 /*-----------------------------------------------------------------*/
1075 /* pic16_sameRegs - two asmops have the same registers                   */
1076 /*-----------------------------------------------------------------*/
1077 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1078 {
1079     int i;
1080
1081     if (aop1 == aop2)
1082         return TRUE ;
1083
1084     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1085                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1086
1087     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1088
1089     if (aop1->type != AOP_REG ||
1090         aop2->type != AOP_REG )
1091         return FALSE ;
1092
1093     /* This is a bit too restrictive if one is a subset of the other...
1094     if (aop1->size != aop2->size )
1095         return FALSE ;
1096     */
1097
1098     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1099 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1100
1101 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1102         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1103             return FALSE ;
1104     }
1105
1106     return TRUE ;
1107 }
1108
1109 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1110 {
1111     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1112                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1113
1114     if(aop1 == aop2)return TRUE;
1115     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1116       
1117       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1118     
1119   return TRUE;
1120 }
1121
1122
1123 /*-----------------------------------------------------------------*/
1124 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1125 /*-----------------------------------------------------------------*/
1126 void pic16_aopOp (operand *op, iCode *ic, bool result)
1127 {
1128     asmop *aop;
1129     symbol *sym;
1130     int i;
1131
1132     if (!op)
1133         return ;
1134
1135     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1136
1137     /* if this a literal */
1138     if (IS_OP_LITERAL(op)) {
1139         op->aop = aop = newAsmop(AOP_LIT);
1140         aop->aopu.aop_lit = op->operand.valOperand;
1141         aop->size = getSize(operandType(op));
1142         return;
1143     }
1144
1145     {
1146       sym_link *type = operandType(op);
1147 #if 0
1148       if(IS_PTR_CONST(type))
1149 #else
1150       if(IS_CODEPTR(type))
1151 #endif
1152         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1153     }
1154
1155     /* if already has a asmop then continue */
1156     if (op->aop)
1157         return ;
1158
1159     /* if the underlying symbol has a aop */
1160     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1161       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1162         op->aop = OP_SYMBOL(op)->aop;
1163         return;
1164     }
1165
1166     /* if this is a true symbol */
1167     if (IS_TRUE_SYMOP(op)) {    
1168         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1169       op->aop = aopForSym(ic, op, result);
1170       return ;
1171     }
1172
1173     /* this is a temporary : this has
1174     only four choices :
1175     a) register
1176     b) spillocation
1177     c) rematerialize 
1178     d) conditional   
1179     e) can be a return use only */
1180
1181     sym = OP_SYMBOL(op);
1182
1183     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1184     /* if the type is a conditional */
1185     if (sym->regType == REG_CND) {
1186         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1187         aop->size = 0;
1188         return;
1189     }
1190
1191     /* if it is spilt then two situations
1192     a) is rematerialize 
1193     b) has a spill location */
1194     if (sym->isspilt || sym->nRegs == 0) {
1195
1196 //      debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
1197       DEBUGpic16_emitcode(";","%d",__LINE__);
1198         /* rematerialize it NOW */
1199         if (sym->remat) {
1200
1201             sym->aop = op->aop = aop = aopForRemat (op);
1202 //            aop->size = getSize(sym->type);
1203 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1204             return;
1205         }
1206
1207 #if 1
1208         if (sym->accuse) {
1209             int i;
1210             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1211             aop->size = getSize(sym->type);
1212             for ( i = 0 ; i < 1 ; i++ ) {
1213                 aop->aopu.aop_str[i] = accUse[i];
1214 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1215             }
1216             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1217             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1218             return;  
1219         }
1220 #endif
1221
1222 #if 1
1223         if (sym->ruonly ) {
1224           /*
1225           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1226           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1227           //pic16_allocDirReg (IC_LEFT(ic));
1228           aop->size = getSize(sym->type);
1229           */
1230
1231           unsigned i;
1232
1233           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1234           aop->size = getSize(sym->type);
1235           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1236             aop->aopu.aop_str[i] = fReturn[i];
1237
1238           DEBUGpic16_emitcode(";","%d",__LINE__);
1239           return;
1240         }
1241 #endif
1242         /* else spill location  */
1243         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1244             /* force a new aop if sizes differ */
1245             sym->usl.spillLoc->aop = NULL;
1246         }
1247
1248 #if 0
1249         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1250                             __FUNCTION__,__LINE__,
1251                             sym->usl.spillLoc->rname,
1252                             sym->rname, sym->usl.spillLoc->offset);
1253 #endif
1254
1255         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1256         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1257         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1258           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1259                                                   getSize(sym->type), 
1260                                                   sym->usl.spillLoc->offset, op);
1261         } else {
1262           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1263           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1264           assert (getSize(sym->type) <= 1);
1265           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1266         }
1267         aop->size = getSize(sym->type);
1268
1269         return;
1270     }
1271
1272     {
1273       sym_link *type = operandType(op);
1274 #if 0
1275       if(IS_PTR_CONST(type)) 
1276 #else
1277       if(IS_CODEPTR(type)) 
1278 #endif
1279         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1280     }
1281
1282     /* must be in a register */
1283     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1284     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1285     aop->size = sym->nRegs;
1286     for ( i = 0 ; i < sym->nRegs ;i++)
1287         aop->aopu.aop_reg[i] = sym->regs[i];
1288 }
1289
1290 /*-----------------------------------------------------------------*/
1291 /* pic16_freeAsmop - free up the asmop given to an operand               */
1292 /*----------------------------------------------------------------*/
1293 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1294 {   
1295     asmop *aop ;
1296
1297     if (!op)
1298         aop = aaop;
1299     else 
1300         aop = op->aop;
1301
1302     if (!aop)
1303         return ;
1304
1305     if (aop->freed)
1306         goto dealloc; 
1307
1308     aop->freed = 1;
1309
1310     /* depending on the asmop type only three cases need work AOP_RO
1311        , AOP_R1 && AOP_STK */
1312 #if 1
1313     switch (aop->type) {
1314         case AOP_FSR0 :
1315             if (_G.fsr0Pushed ) {
1316                 if (pop) {
1317                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1318                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1319 //                    pic16_emitcode ("pop","ar0");
1320                     _G.fsr0Pushed--;
1321                 }
1322             }
1323             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1324             break;
1325
1326         case AOP_FSR2 :
1327             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1328             break;
1329
1330         case AOP_R0 :
1331             if (_G.r0Pushed ) {
1332                 if (pop) {
1333                     pic16_emitcode ("pop","ar0");     
1334                     _G.r0Pushed--;
1335                 }
1336             }
1337             bitVectUnSetBit(ic->rUsed,R0_IDX);
1338             break;
1339
1340         case AOP_R1 :
1341             if (_G.r1Pushed ) {
1342                 if (pop) {
1343                     pic16_emitcode ("pop","ar1");
1344                     _G.r1Pushed--;
1345                 }
1346             }
1347             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1348             break;
1349
1350         case AOP_STA:
1351           {
1352             int i;
1353
1354               /* we must store the result on stack */
1355               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1356                 // operands on stack are accessible via "FSR2 + index" with index
1357                 // starting at 2 for arguments and growing from 0 downwards for
1358                 // local variables (index == 0 is not assigned so we add one here)
1359                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1360                 if (soffs <= 0) {
1361                   assert (soffs < 0);
1362                   soffs++;
1363                 } // if
1364                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1365                 for(i=0;i<aop->size;i++) {
1366                   /* initialise for stack access via frame pointer */
1367                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1368                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1369                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1370                 }
1371         
1372                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1373               }
1374
1375               if(!_G.resDirect) {
1376                 for(i=0;i<aop->size;i++)
1377                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1378               }
1379               _G.resDirect = 0;
1380           }
1381           break;
1382 #if 0
1383         case AOP_STK :
1384         {
1385             int sz = aop->size;    
1386             int stk = aop->aopu.aop_stk + aop->size;
1387             bitVectUnSetBit(ic->rUsed,R0_IDX);
1388             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1389
1390             getFreePtr(ic,&aop,FALSE);
1391             
1392             if (options.stack10bit)
1393             {
1394                 /* I'm not sure what to do here yet... */
1395                 /* #STUB */
1396                 fprintf(stderr, 
1397                         "*** Warning: probably generating bad code for "
1398                         "10 bit stack mode.\n");
1399             }
1400             
1401             if (stk) {
1402                 pic16_emitcode ("mov","a,_bp");
1403                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1404                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1405             } else {
1406                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1407             }
1408
1409             while (sz--) {
1410                 pic16_emitcode("pop","acc");
1411                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1412                 if (!sz) break;
1413                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1414             }
1415             op->aop = aop;
1416             pic16_freeAsmop(op,NULL,ic,TRUE);
1417             if (_G.r0Pushed) {
1418                 pic16_emitcode("pop","ar0");
1419                 _G.r0Pushed--;
1420             }
1421
1422             if (_G.r1Pushed) {
1423                 pic16_emitcode("pop","ar1");
1424                 _G.r1Pushed--;
1425             }       
1426         }
1427 #endif
1428
1429     }
1430 #endif
1431
1432 dealloc:
1433     /* all other cases just dealloc */
1434     if (op ) {
1435         op->aop = NULL;
1436         if (IS_SYMOP(op)) {
1437             OP_SYMBOL(op)->aop = NULL;    
1438             /* if the symbol has a spill */
1439             if (SPIL_LOC(op))
1440                 SPIL_LOC(op)->aop = NULL;
1441         }
1442     }
1443 }
1444
1445 /*-----------------------------------------------------------------*/
1446 /* pic16_aopGet - for fetching value of the aop                          */
1447 /*-----------------------------------------------------------------*/
1448 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1449 {
1450     char *s = buffer ;
1451     char *rs;
1452
1453     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1454
1455     /* offset is greater than size then zero */
1456     if (offset > (aop->size - 1) &&
1457         aop->type != AOP_LIT)
1458         return zero;
1459
1460     /* depending on type */
1461     switch (aop->type) {
1462
1463     case AOP_FSR0:
1464     case AOP_FSR2:
1465       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1466       rs = Safe_calloc(1, strlen(s)+1);
1467       strcpy(rs, s);
1468       return (rs);
1469       
1470 #if 0
1471       /* if we need to increment it */
1472       while (offset > aop->coff)
1473         {
1474           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1475           aop->coff++;
1476         }
1477
1478       while (offset < aop->coff)
1479         {
1480           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1481           aop->coff--;
1482         }
1483       aop->coff = offset;
1484       if (aop->paged)
1485         {
1486           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1487           return (dname ? "acc" : "a");
1488         }
1489       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1490       rs = Safe_calloc (1, strlen (s) + 1);
1491       strcpy (rs, s);
1492       return rs;
1493 #endif
1494
1495         
1496     case AOP_IMMD:
1497         if (bit16) 
1498             sprintf (s,"%s",aop->aopu.aop_immd);
1499         else
1500             if (offset) 
1501                 sprintf(s,"(%s >> %d)",
1502                         aop->aopu.aop_immd,
1503                         offset*8);
1504             else
1505                 sprintf(s,"%s",
1506                         aop->aopu.aop_immd);
1507         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1508         rs = Safe_calloc(1,strlen(s)+1);
1509         strcpy(rs,s);   
1510         return rs;
1511         
1512     case AOP_DIR:
1513       if (offset) {
1514         sprintf(s,"(%s + %d)",
1515                 aop->aopu.aop_dir,
1516                 offset);
1517         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1518       } else
1519             sprintf(s,"%s",aop->aopu.aop_dir);
1520         rs = Safe_calloc(1,strlen(s)+1);
1521         strcpy(rs,s);   
1522         return rs;
1523         
1524     case AOP_REG:
1525       //if (dname) 
1526       //    return aop->aopu.aop_reg[offset]->dname;
1527       //else
1528             return aop->aopu.aop_reg[offset]->name;
1529         
1530     case AOP_CRY:
1531       //pic16_emitcode(";","%d",__LINE__);
1532       return aop->aopu.aop_dir;
1533         
1534     case AOP_ACC:
1535         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1536 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1537 //        assert( 0 );
1538 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1539         rs = Safe_strdup("WREG");
1540         return (rs);
1541
1542     case AOP_LIT:
1543         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1544         rs = Safe_calloc(1,strlen(s)+1);
1545         strcpy(rs,s);   
1546         return rs;
1547         
1548     case AOP_STR:
1549         aop->coff = offset ;
1550         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1551             dname)
1552             return "acc";
1553         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1554         
1555         return aop->aopu.aop_str[offset];
1556         
1557     case AOP_PCODE:
1558       {
1559         pCodeOp *pcop = aop->aopu.pcop;
1560         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1561         if(pcop->name) {
1562           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1563           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1564           if (offset) {
1565             sprintf(s,"(%s + %d)", pcop->name, offset);
1566           } else {
1567             sprintf(s,"%s", pcop->name);
1568           }
1569         } else
1570           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1571
1572       }
1573       rs = Safe_calloc(1,strlen(s)+1);
1574       strcpy(rs,s);   
1575       return rs;
1576
1577 #if 0
1578     case AOP_PAGED:
1579       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1580       if (offset) {
1581         sprintf(s,"(%s + %d)",
1582                 aop->aopu.aop_dir,
1583                 offset);
1584       } else
1585             sprintf(s,"%s",aop->aopu.aop_dir);
1586       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1587       rs = Safe_calloc(1,strlen(s)+1);
1588       strcpy(rs,s);   
1589       return rs;
1590 #endif
1591
1592     case AOP_STA:
1593         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1594         return (rs);
1595         
1596     case AOP_STK:
1597 //        pCodeOp *pcop = aop->aop
1598         break;
1599
1600     }
1601
1602     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1603     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604            "aopget got unsupported aop->type");
1605     exit(0);
1606 }
1607
1608
1609
1610 /* lock has the following meaning: When allocating temporary registers
1611  * for stack variables storage, the value of the temporary register is
1612  * saved on stack. Its value is restored at the end. This procedure is
1613  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1614  * a possibility that before a call to pic16_aopOp, a temporary register
1615  * is allocated for a while and it is freed after some time, this will
1616  * mess the stack and values will not be restored properly. So use lock=1
1617  * to allocate temporary registers used internally by the programmer, and
1618  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1619  * to inform the compiler developer about a possible bug. This is an internal
1620  * feature for developing the compiler -- VR */
1621  
1622 int _TempReg_lock = 0;
1623 /*-----------------------------------------------------------------*/
1624 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1625 /*-----------------------------------------------------------------*/
1626 pCodeOp *pic16_popGetTempReg(int lock)
1627 {
1628   pCodeOp *pcop;
1629   symbol *cfunc;
1630
1631 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1632     if(_TempReg_lock) {
1633 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1634     }
1635     
1636     _TempReg_lock += lock;
1637     
1638     cfunc = currFunc;
1639     currFunc = NULL;
1640
1641     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1642     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1643       PCOR(pcop)->r->wasUsed=1;
1644       PCOR(pcop)->r->isFree=0;
1645
1646       /* push value on stack */
1647       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1648     }
1649
1650     currFunc = cfunc;
1651
1652   return pcop;
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1657 /*                            don't save if inside v               */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1660 {
1661   pCodeOp *pcop;
1662   symbol *cfunc;
1663
1664 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1665
1666     if(_TempReg_lock) {
1667 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1668     }
1669
1670     _TempReg_lock += lock;
1671
1672     cfunc = currFunc;
1673     currFunc = NULL;
1674
1675     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1676     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1677       PCOR(pcop)->r->wasUsed=1;
1678       PCOR(pcop)->r->isFree=0;
1679
1680       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1681       /* push value on stack */
1682         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1683       }
1684     }
1685
1686     currFunc = cfunc;
1687
1688   return pcop;
1689 }
1690
1691
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1694 /*-----------------------------------------------------------------*/
1695 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1696 {
1697   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698
1699   _TempReg_lock -= lock;
1700
1701   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1702     PCOR(pcop)->r->isFree = 1;
1703     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1704   }
1705 }
1706 /*-----------------------------------------------------------------*/
1707 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1708 /*-----------------------------------------------------------------*/
1709 pCodeOp *pic16_popGetLabel(unsigned int key)
1710 {
1711
1712   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1713
1714   if(key>max_key)
1715     max_key = key;
1716
1717   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1718 }
1719
1720 /*-----------------------------------------------------------------*/
1721 /* pic16_popCopyReg - copy a pcode operator                              */
1722 /*-----------------------------------------------------------------*/
1723 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1724 {
1725   pCodeOpReg *pcor;
1726
1727   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1728   pcor->pcop.type = pc->pcop.type;
1729   if(pc->pcop.name) {
1730     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1731       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1732   } else
1733     pcor->pcop.name = NULL;
1734
1735   pcor->r = pc->r;
1736   pcor->rIdx = pc->rIdx;
1737   pcor->r->wasUsed=1;
1738   pcor->instance = pc->instance;
1739
1740 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1741
1742   return PCOP(pcor);
1743 }
1744
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1747 /*-----------------------------------------------------------------*/
1748 pCodeOp *pic16_popGetLit(int lit)
1749 {
1750   return pic16_newpCodeOpLit(lit);
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1755 /*-----------------------------------------------------------------*/
1756 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1757 {
1758   return pic16_newpCodeOpLit2(lit, arg2);
1759 }
1760
1761
1762 /*-----------------------------------------------------------------*/
1763 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1764 /*-----------------------------------------------------------------*/
1765 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1766 {
1767   return pic16_newpCodeOpImmd(name, offset,index, 0);
1768 }
1769
1770
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGet - asm operator to pcode operator conversion              */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetWithString(char *str)
1775 {
1776   pCodeOp *pcop;
1777
1778
1779   if(!str) {
1780     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1781     exit (1);
1782   }
1783
1784   pcop = pic16_newpCodeOp(str,PO_STR);
1785
1786   return pcop;
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popRegFromString -                                        */
1791 /*-----------------------------------------------------------------*/
1792 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1793 {
1794
1795   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1796   pcop->type = PO_DIR;
1797
1798   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1799   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1800
1801   if(!str)
1802     str = "BAD_STRING";
1803
1804   pcop->name = Safe_calloc(1,strlen(str)+1);
1805   strcpy(pcop->name,str);
1806
1807   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1808
1809   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1810
1811   /* make sure that register doesn't exist,
1812    * and operand isn't NULL
1813    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1814   if((PCOR(pcop)->r == NULL) 
1815     && (op)
1816     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1817 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1818 //              __FUNCTION__, __LINE__, str, size, offset);
1819
1820     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1821     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1822
1823   }
1824   PCOR(pcop)->instance = offset;
1825
1826   return pcop;
1827 }
1828
1829 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1830 {
1831   pCodeOp *pcop;
1832
1833 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1834
1835         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1836         PCOR(pcop)->rIdx = rIdx;
1837         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1838
1839         PCOR(pcop)->r->isFree = 0;
1840         PCOR(pcop)->r->wasUsed = 1;
1841
1842         pcop->type = PCOR(pcop)->r->pc_type;
1843
1844   return pcop;
1845 }
1846
1847 /*---------------------------------------------------------------------------------*/
1848 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1849 /*                 VR 030601                                                       */
1850 /*---------------------------------------------------------------------------------*/
1851 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1852 {
1853   pCodeOpReg2 *pcop2;
1854   pCodeOp *temp;
1855   
1856         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1857
1858         /* comment the following check, so errors to throw up */
1859 //      if(!pcop2)return NULL;
1860
1861         temp = pic16_popGet(aop_dst, offset);
1862         pcop2->pcop2 = temp;
1863         
1864   return PCOP(pcop2);
1865 }
1866
1867
1868
1869 /*--------------------------------------------------------------------------------.-*/
1870 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1871 /*                  VR 030601 , adapted by Hans Dorn                                */
1872 /*--------------------------------------------------------------------------------.-*/
1873 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1874 {
1875   pCodeOpReg2 *pcop2;
1876  
1877         pcop2 = (pCodeOpReg2 *)src;
1878         pcop2->pcop2 = dst;
1879         
1880         return PCOP(pcop2);
1881 }
1882
1883
1884
1885 /*---------------------------------------------------------------------------------*/
1886 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1887 /*                     movff instruction                                           */
1888 /*---------------------------------------------------------------------------------*/
1889 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1890 {
1891   pCodeOpReg2 *pcop2;
1892
1893         if(!noalloc) {
1894                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1895                 pcop2->pcop2 = pic16_popCopyReg(dst);
1896         } else {
1897                 /* the pCodeOp may be already allocated */
1898                 pcop2 = (pCodeOpReg2 *)(src);
1899                 pcop2->pcop2 = (pCodeOp *)(dst);
1900         }
1901
1902   return PCOP(pcop2);
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGet - asm operator to pcode operator conversion              */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1910 {
1911   //char *s = buffer ;
1912   char *rs;
1913   pCodeOp *pcop;
1914
1915     FENTRY2;
1916     /* offset is greater than
1917     size then zero */
1918
1919 //    if (offset > (aop->size - 1) &&
1920 //        aop->type != AOP_LIT)
1921 //      return NULL;  //zero;
1922
1923     /* depending on type */
1924     switch (aop->type) {
1925         
1926     case AOP_R0:
1927     case AOP_R1:
1928     case AOP_DPTR:
1929     case AOP_DPTR2:
1930         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1931         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1932         assert( 0 );
1933         return NULL;
1934
1935
1936     case AOP_FSR0:
1937     case AOP_FSR2:
1938       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1939       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1940       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1941       PCOR(pcop)->r->wasUsed = 1;
1942       PCOR(pcop)->r->isFree = 0;
1943       
1944       PCOR(pcop)->instance = offset;
1945       pcop->type = PCOR(pcop)->r->pc_type;
1946       return (pcop);
1947
1948     case AOP_IMMD:
1949       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1950       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1951
1952     case AOP_STA:
1953       /* pCodeOp is already allocated from aopForSym */
1954         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1955         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1956           
1957       return (pcop);
1958       
1959     case AOP_ACC:
1960       {
1961         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1962
1963         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1964
1965         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1966         
1967         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1968         PCOR(pcop)->rIdx = rIdx;
1969         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1970         PCOR(pcop)->r->wasUsed=1;
1971         PCOR(pcop)->r->isFree=0;
1972
1973         PCOR(pcop)->instance = offset;
1974         pcop->type = PCOR(pcop)->r->pc_type;
1975 //      rs = aop->aopu.aop_reg[offset]->name;
1976 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1977         return pcop;
1978
1979
1980 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1981 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1982
1983 //      assert( 0 );
1984       }
1985         
1986     case AOP_DIR:
1987       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1988       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1989         
1990 #if 0
1991     case AOP_PAGED:
1992       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1993       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1994 #endif
1995
1996     case AOP_REG:
1997       {
1998         int rIdx;
1999         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2000         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2001
2002         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2003         
2004         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2005 //      pcop->type = PO_GPR_REGISTER;
2006         PCOR(pcop)->rIdx = rIdx;
2007         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2008         PCOR(pcop)->r->wasUsed=1;
2009         PCOR(pcop)->r->isFree=0;
2010
2011         PCOR(pcop)->instance = offset;
2012         pcop->type = PCOR(pcop)->r->pc_type;
2013         
2014         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2015         rs = aop->aopu.aop_reg[offset]->name;
2016         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2017         return pcop;
2018       }
2019
2020     case AOP_CRY:
2021         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2022
2023       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2024       PCOR(pcop)->instance = offset;
2025       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2026       //if(PCOR(pcop)->r == NULL)
2027       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2028       return pcop;
2029         
2030     case AOP_LIT:
2031         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2032       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2033
2034     case AOP_STR:
2035       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2036       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2037
2038       /*
2039       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2040       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2041       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2042       pcop->type = PCOR(pcop)->r->pc_type;
2043       pcop->name = PCOR(pcop)->r->name;
2044
2045       return pcop;
2046       */
2047
2048     case AOP_PCODE:
2049       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2050                           __LINE__, 
2051                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2052       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2053       switch( aop->aopu.pcop->type ) {
2054         case PO_DIR: PCOR(pcop)->instance += offset; break;
2055         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2056         case PO_WREG: assert (offset==0); break;
2057         default:
2058           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2059           assert( 0 );  /* should never reach here */;
2060       }
2061       return pcop;
2062     }
2063
2064     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2065            "pic16_popGet got unsupported aop->type");
2066     exit(0);
2067 }
2068 /*-----------------------------------------------------------------*/
2069 /* pic16_aopPut - puts a string for a aop                                */
2070 /*-----------------------------------------------------------------*/
2071 void pic16_aopPut (asmop *aop, char *s, int offset)
2072 {
2073     char *d = buffer ;
2074     symbol *lbl ;
2075
2076     return;
2077
2078     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2079
2080     if (aop->size && offset > ( aop->size - 1)) {
2081         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2082                "pic16_aopPut got offset > aop->size");
2083         exit(0);
2084     }
2085
2086     /* will assign value to value */
2087     /* depending on where it is ofcourse */
2088     switch (aop->type) {
2089     case AOP_DIR:
2090       if (offset) {
2091         sprintf(d,"(%s + %d)",
2092                 aop->aopu.aop_dir,offset);
2093         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2094
2095       } else
2096             sprintf(d,"%s",aop->aopu.aop_dir);
2097         
2098         if (strcmp(d,s)) {
2099           DEBUGpic16_emitcode(";","%d",__LINE__);
2100           if(strcmp(s,"W"))
2101             pic16_emitcode("movf","%s,w",s);
2102           pic16_emitcode("movwf","%s",d);
2103
2104           if(strcmp(s,"W")) {
2105             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2106             if(offset >= aop->size) {
2107               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2108               break;
2109             } else
2110               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2111           }
2112
2113           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2114
2115
2116         }
2117         break;
2118         
2119     case AOP_REG:
2120       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2121         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2122           /*
2123             if (*s == '@'           ||
2124                 strcmp(s,"r0") == 0 ||
2125                 strcmp(s,"r1") == 0 ||
2126                 strcmp(s,"r2") == 0 ||
2127                 strcmp(s,"r3") == 0 ||
2128                 strcmp(s,"r4") == 0 ||
2129                 strcmp(s,"r5") == 0 ||
2130                 strcmp(s,"r6") == 0 || 
2131                 strcmp(s,"r7") == 0 )
2132                 pic16_emitcode("mov","%s,%s  ; %d",
2133                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2134             else
2135           */
2136
2137           if(strcmp(s,"W")==0 )
2138             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2139
2140           pic16_emitcode("movwf","%s",
2141                    aop->aopu.aop_reg[offset]->name);
2142
2143           if(strcmp(s,zero)==0) {
2144             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2145
2146           } else if(strcmp(s,"W")==0) {
2147             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2148             pcop->type = PO_GPR_REGISTER;
2149
2150             PCOR(pcop)->rIdx = -1;
2151             PCOR(pcop)->r = NULL;
2152
2153             DEBUGpic16_emitcode(";","%d",__LINE__);
2154             pcop->name = Safe_strdup(s);
2155             pic16_emitpcode(POC_MOVFW,pcop);
2156             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2157           } else if(strcmp(s,one)==0) {
2158             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2159             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2160           } else {
2161             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2162           }
2163         }
2164         break;
2165         
2166     case AOP_DPTR:
2167     case AOP_DPTR2:
2168     
2169     if (aop->type == AOP_DPTR2)
2170     {
2171         genSetDPTR(1);
2172     }
2173     
2174         if (aop->code) {
2175             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2176                    "pic16_aopPut writting to code space");
2177             exit(0);
2178         }
2179         
2180         while (offset > aop->coff) {
2181             aop->coff++;
2182             pic16_emitcode ("inc","dptr");
2183         }
2184         
2185         while (offset < aop->coff) {
2186             aop->coff-- ;
2187             pic16_emitcode("lcall","__decdptr");
2188         }
2189         
2190         aop->coff = offset;
2191         
2192         /* if not in accumulater */
2193         MOVA(s);        
2194         
2195         pic16_emitcode ("movx","@dptr,a");
2196         
2197     if (aop->type == AOP_DPTR2)
2198     {
2199         genSetDPTR(0);
2200     }
2201         break;
2202         
2203     case AOP_R0:
2204     case AOP_R1:
2205         while (offset > aop->coff) {
2206             aop->coff++;
2207             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2208         }
2209         while (offset < aop->coff) {
2210             aop->coff-- ;
2211             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2212         }
2213         aop->coff = offset;
2214         
2215         if (aop->paged) {
2216             MOVA(s);           
2217             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2218             
2219         } else
2220             if (*s == '@') {
2221                 MOVA(s);
2222                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2223             } else
2224                 if (strcmp(s,"r0") == 0 ||
2225                     strcmp(s,"r1") == 0 ||
2226                     strcmp(s,"r2") == 0 ||
2227                     strcmp(s,"r3") == 0 ||
2228                     strcmp(s,"r4") == 0 ||
2229                     strcmp(s,"r5") == 0 ||
2230                     strcmp(s,"r6") == 0 || 
2231                     strcmp(s,"r7") == 0 ) {
2232                     char buffer[10];
2233                     sprintf(buffer,"a%s",s);
2234                     pic16_emitcode("mov","@%s,%s",
2235                              aop->aopu.aop_ptr->name,buffer);
2236                 } else
2237                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2238         
2239         break;
2240         
2241     case AOP_STK:
2242         if (strcmp(s,"a") == 0)
2243             pic16_emitcode("push","acc");
2244         else
2245             pic16_emitcode("push","%s",s);
2246         
2247         break;
2248         
2249     case AOP_CRY:
2250         /* if bit variable */
2251         if (!aop->aopu.aop_dir) {
2252             pic16_emitcode("clr","a");
2253             pic16_emitcode("rlc","a");
2254         } else {
2255             if (s == zero) 
2256                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2257             else
2258                 if (s == one)
2259                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2260                 else
2261                     if (!strcmp(s,"c"))
2262                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2263                     else {
2264                         lbl = newiTempLabel(NULL);
2265                         
2266                         if (strcmp(s,"a")) {
2267                             MOVA(s);
2268                         }
2269                         pic16_emitcode("clr","c");
2270                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2271                         pic16_emitcode("cpl","c");
2272                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2273                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2274                     }
2275         }
2276         break;
2277         
2278     case AOP_STR:
2279         aop->coff = offset;
2280         if (strcmp(aop->aopu.aop_str[offset],s))
2281             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2282         break;
2283         
2284     case AOP_ACC:
2285         aop->coff = offset;
2286         if (!offset && (strcmp(s,"acc") == 0))
2287             break;
2288         
2289         if (strcmp(aop->aopu.aop_str[offset],s))
2290             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2291         break;
2292
2293     default :
2294         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2295 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2296 //             "pic16_aopPut got unsupported aop->type");
2297 //      exit(0);    
2298     }    
2299
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2304 /*-----------------------------------------------------------------*/
2305 void pic16_mov2w (asmop *aop, int offset)
2306 {
2307   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2308
2309   if(is_LitAOp(aop))
2310     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2311   else
2312     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2313 }
2314
2315 static void mov2f(asmop *dst, asmop *src, int offset)
2316 {
2317   if(is_LitAOp(src)) {
2318     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2319     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2320   } else {
2321     if(pic16_sameRegsOfs(src, dst, offset))return;
2322     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2323                       pic16_popGet(dst, offset)));
2324   }
2325 }
2326
2327 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2328 {
2329   if(is_LitAOp(src)) {
2330     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2331     pic16_emitpcode(POC_MOVWF, dst);
2332   } else {
2333     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2334   }
2335 }
2336
2337 void pic16_testStackOverflow(void)
2338 {
2339 #define GSTACK_TEST_NAME        "__gstack_test"
2340
2341   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2342   
2343   {
2344     symbol *sym;
2345
2346       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2347       strcpy(sym->rname, GSTACK_TEST_NAME);
2348       checkAddSym(&externs, sym);
2349   }
2350
2351 }
2352
2353 /* push pcop into stack */
2354 void pic16_pushpCodeOp(pCodeOp *pcop)
2355 {
2356 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2357   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2358   if(pic16_options.gstack)
2359     pic16_testStackOverflow();
2360     
2361 }
2362
2363 /* pop pcop from stack */
2364 void pic16_poppCodeOp(pCodeOp *pcop)
2365 {
2366   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2367   if(pic16_options.gstack)
2368     pic16_testStackOverflow();
2369 }
2370
2371
2372 /*-----------------------------------------------------------------*/
2373 /* pushw - pushes wreg to stack                                    */
2374 /*-----------------------------------------------------------------*/
2375 void pushw(void)
2376 {
2377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2379   if(pic16_options.gstack)
2380     pic16_testStackOverflow();
2381 }
2382
2383                 
2384 /*-----------------------------------------------------------------*/
2385 /* pushaop - pushes aop to stack                                   */
2386 /*-----------------------------------------------------------------*/
2387 void pushaop(asmop *aop, int offset)
2388 {
2389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2390
2391   if(is_LitAOp(aop)) {
2392     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2393     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2394   } else {
2395     pic16_emitpcode(POC_MOVFF,
2396       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2397   }
2398
2399   if(pic16_options.gstack)
2400     pic16_testStackOverflow();
2401 }
2402
2403 /*-----------------------------------------------------------------*/
2404 /* popaop - pops aop from stack                                    */
2405 /*-----------------------------------------------------------------*/
2406 void popaop(asmop *aop, int offset)
2407 {
2408   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2409   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2410   if(pic16_options.gstack)
2411     pic16_testStackOverflow();
2412 }
2413
2414 void popaopidx(asmop *aop, int offset, int index)
2415 {
2416   int ofs=1;
2417
2418     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2419
2420     if(STACK_MODEL_LARGE)ofs++;
2421
2422     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2423     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2424     if(pic16_options.gstack)
2425       pic16_testStackOverflow();
2426 }
2427
2428 #if !(USE_GENERIC_SIGNED_SHIFT)
2429 /*-----------------------------------------------------------------*/
2430 /* reAdjustPreg - points a register back to where it should        */
2431 /*-----------------------------------------------------------------*/
2432 static void reAdjustPreg (asmop *aop)
2433 {
2434     int size ;
2435
2436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2437     aop->coff = 0;
2438     if ((size = aop->size) <= 1)
2439         return ;
2440     size-- ;
2441     switch (aop->type) {
2442         case AOP_R0 :
2443         case AOP_R1 :
2444             while (size--)
2445                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2446             break;          
2447         case AOP_DPTR :
2448         case AOP_DPTR2:
2449             if (aop->type == AOP_DPTR2)
2450             {
2451                 genSetDPTR(1);
2452             } 
2453             while (size--)
2454             {
2455                 pic16_emitcode("lcall","__decdptr");
2456             }
2457                 
2458             if (aop->type == AOP_DPTR2)
2459             {
2460                 genSetDPTR(0);
2461             }                
2462             break;  
2463
2464     }   
2465
2466 }
2467 #endif
2468
2469 #if 0
2470 /*-----------------------------------------------------------------*/
2471 /* opIsGptr: returns non-zero if the passed operand is             */   
2472 /* a generic pointer type.                                         */
2473 /*-----------------------------------------------------------------*/ 
2474 static int opIsGptr(operand *op)
2475 {
2476     sym_link *type = operandType(op);
2477     
2478     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2479     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2480     {
2481         return 1;
2482     }
2483     return 0;        
2484 }
2485 #endif
2486
2487 /*-----------------------------------------------------------------*/
2488 /* pic16_getDataSize - get the operand data size                         */
2489 /*-----------------------------------------------------------------*/
2490 int pic16_getDataSize(operand *op)
2491 {
2492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493
2494
2495     return AOP_SIZE(op);
2496
2497     // tsd- in the pic port, the genptr size is 1, so this code here
2498     // fails. ( in the 8051 port, the size was 4).
2499 #if 0
2500     int size;
2501     size = AOP_SIZE(op);
2502     if (size == GPTRSIZE)
2503     {
2504         sym_link *type = operandType(op);
2505         if (IS_GENPTR(type))
2506         {
2507             /* generic pointer; arithmetic operations
2508              * should ignore the high byte (pointer type).
2509              */
2510             size--;
2511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2512         }
2513     }
2514     return size;
2515 #endif
2516 }
2517
2518 /*-----------------------------------------------------------------*/
2519 /* pic16_outAcc - output Acc                                             */
2520 /*-----------------------------------------------------------------*/
2521 void pic16_outAcc(operand *result)
2522 {
2523   int size,offset;
2524   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2525   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2526
2527
2528   size = pic16_getDataSize(result);
2529   if(size){
2530     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2531     size--;
2532     offset = 1;
2533     /* unsigned or positive */
2534     while(size--)
2535       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2536   }
2537
2538 }
2539
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_outBitC - output a bit C                                  */
2542 /*                 Move to result the value of Carry flag -- VR    */
2543 /*-----------------------------------------------------------------*/
2544 void pic16_outBitC(operand *result)
2545 {
2546   int i;
2547
2548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2549
2550     /* if the result is bit */
2551     if (AOP_TYPE(result) == AOP_CRY) {
2552         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2553         pic16_aopPut(AOP(result),"c",0);
2554     } else {
2555
2556         i = AOP_SIZE(result);
2557         while(i--) {
2558                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2559         }
2560         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2561     }
2562 }
2563
2564 /*-----------------------------------------------------------------*/
2565 /* pic16_outBitOp - output a bit from Op                           */
2566 /*                 Move to result the value of set/clr op -- VR    */
2567 /*-----------------------------------------------------------------*/
2568 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2569 {
2570   int i;
2571
2572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2573
2574     /* if the result is bit */
2575     if (AOP_TYPE(result) == AOP_CRY) {
2576         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2577         pic16_aopPut(AOP(result),"c",0);
2578     } else {
2579
2580         i = AOP_SIZE(result);
2581         while(i--) {
2582                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2583         }
2584         pic16_emitpcode(POC_RRCF, pcop);          
2585         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2586     }
2587 }
2588
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_toBoolean(operand *oper)
2593 {
2594     int size = AOP_SIZE(oper) - 1;
2595     int offset = 1;
2596
2597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2598
2599     if ( AOP_TYPE(oper) != AOP_ACC) {
2600       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2601     }
2602     while (size--) {
2603       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2604     }
2605 }
2606
2607
2608 #if !defined(GEN_Not)
2609 /*-----------------------------------------------------------------*/
2610 /* genNot - generate code for ! operation                          */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genNot (iCode *ic)
2613 {
2614   symbol *tlbl;
2615   int size;
2616
2617   FENTRY;
2618   /* assign asmOps to operand & result */
2619   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2621
2622   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2623   /* if in bit space then a special case */
2624   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2625     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2626       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2627       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2628     } else {
2629       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2630       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2632     }
2633     goto release;
2634   }
2635
2636   size = AOP_SIZE(IC_LEFT(ic));
2637   if(size == 1) {
2638     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2639     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2640     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2641     goto release;
2642   }
2643   pic16_toBoolean(IC_LEFT(ic));
2644
2645   tlbl = newiTempLabel(NULL);
2646   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2647   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2648   pic16_outBitC(IC_RESULT(ic));
2649
2650  release:    
2651   /* release the aops */
2652   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2654 }
2655 #endif
2656
2657
2658 #if !defined(GEN_Cpl)
2659 /*-----------------------------------------------------------------*/
2660 /* genCpl - generate code for complement                           */
2661 /*-----------------------------------------------------------------*/
2662 static void pic16_genCpl (iCode *ic)
2663 {
2664   int offset = 0;
2665   int size ;
2666
2667     FENTRY;
2668     /* assign asmOps to operand & result */
2669     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2670     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2671
2672     /* if both are in bit space then 
2673     a special case */
2674     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2675         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2676
2677         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2678         pic16_emitcode("cpl","c"); 
2679         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2680         goto release; 
2681     } 
2682
2683     size = AOP_SIZE(IC_RESULT(ic));
2684     while (size--) {
2685 /*
2686         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2687         MOVA(l);       
2688         pic16_emitcode("cpl","a");
2689         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2690 */
2691         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2692               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2693         } else {
2694                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2695                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2696         }
2697         offset++;
2698
2699     }
2700
2701
2702 release:
2703     /* release the aops */
2704     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2705     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2706 }
2707 #endif
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points                */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2713 {
2714   int size ,offset =0 ;
2715   
2716     FENTRY;
2717     /* for this we just need to flip the 
2718     first it then copy the rest in place */
2719     size = AOP_SIZE(op);
2720
2721     while(size--) {
2722       mov2f(AOP(result), AOP(op), offset);
2723       offset++;
2724     }
2725     
2726     /* toggle the MSB's highest bit */
2727     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2728 }
2729
2730 /*-----------------------------------------------------------------*/
2731 /* genUminus - unary minus code generation                         */
2732 /*-----------------------------------------------------------------*/
2733 static void genUminus (iCode *ic)
2734 {
2735   int size, i;
2736   sym_link *optype, *rtype;
2737   symbol *label;
2738   int needLabel=0;
2739
2740     FENTRY;     
2741     
2742     /* assign asmops */
2743     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2744     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2745
2746     /* if both in bit space then special case */
2747     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2748       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2749         
2750         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2751         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2752         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2753         goto release; 
2754     } 
2755
2756     optype = operandType(IC_LEFT(ic));
2757     rtype = operandType(IC_RESULT(ic));
2758
2759     /* if float then do float stuff */
2760     if (IS_FLOAT(optype)) {
2761       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2762       goto release;
2763     }
2764
2765     /* otherwise subtract from zero by taking the 2's complement */
2766     size = AOP_SIZE(IC_LEFT(ic));
2767     label = newiTempLabel ( NULL );
2768     
2769     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2770       for (i=size-1; i > 0; i--) {
2771         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2772       } // for
2773       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2774       for (i=1; i < size; i++) {
2775         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2776         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2777       } // for
2778     } else {
2779       for (i=size-1; i >= 0; i--) {
2780         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2781         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2782       } // for
2783       if (size > 1) {
2784         for (i=0; i < size-2; i++) {
2785           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2786           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2787         } // for
2788         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2789       } // if
2790       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2791     }
2792     if (needLabel)
2793       pic16_emitpLabel (label->key);
2794
2795 release:
2796     /* release the aops */
2797     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2798     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2799 }
2800
2801 #if 0
2802 /*-----------------------------------------------------------------*/
2803 /* saveRegisters - will look for a call and save the registers     */
2804 /*-----------------------------------------------------------------*/
2805 static void saveRegisters(iCode *lic) 
2806 {
2807     int i;
2808     iCode *ic;
2809     bitVect *rsave;
2810     sym_link *dtype;
2811
2812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2813     /* look for call */
2814     for (ic = lic ; ic ; ic = ic->next) 
2815         if (ic->op == CALL || ic->op == PCALL)
2816             break;
2817
2818     if (!ic) {
2819         fprintf(stderr,"found parameter push with no function call\n");
2820         return ;
2821     }
2822
2823     /* if the registers have been saved already then
2824     do nothing */
2825     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2826         return ;
2827
2828     /* find the registers in use at this time 
2829     and push them away to safety */
2830     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2831                           ic->rUsed);
2832
2833     ic->regsSaved = 1;
2834     if (options.useXstack) {
2835         if (bitVectBitValue(rsave,R0_IDX))
2836             pic16_emitcode("mov","b,r0");
2837         pic16_emitcode("mov","r0,%s",spname);
2838         for (i = 0 ; i < pic16_nRegs ; i++) {
2839             if (bitVectBitValue(rsave,i)) {
2840                 if (i == R0_IDX)
2841                     pic16_emitcode("mov","a,b");
2842                 else
2843                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2844                 pic16_emitcode("movx","@r0,a");
2845                 pic16_emitcode("inc","r0");
2846             }
2847         }
2848         pic16_emitcode("mov","%s,r0",spname);
2849         if (bitVectBitValue(rsave,R0_IDX))
2850             pic16_emitcode("mov","r0,b");           
2851     }// else
2852     //for (i = 0 ; i < pic16_nRegs ; i++) {
2853     //    if (bitVectBitValue(rsave,i))
2854     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2855     //}
2856
2857     dtype = operandType(IC_LEFT(ic));
2858     if (currFunc && dtype && 
2859         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2860         IFFUNC_ISISR(currFunc->type) &&
2861         !ic->bankSaved) 
2862
2863         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2864
2865 }
2866 /*-----------------------------------------------------------------*/
2867 /* unsaveRegisters - pop the pushed registers                      */
2868 /*-----------------------------------------------------------------*/
2869 static void unsaveRegisters (iCode *ic)
2870 {
2871     int i;
2872     bitVect *rsave;
2873
2874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2875     /* find the registers in use at this time 
2876     and push them away to safety */
2877     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2878                           ic->rUsed);
2879     
2880     if (options.useXstack) {
2881         pic16_emitcode("mov","r0,%s",spname);   
2882         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2883             if (bitVectBitValue(rsave,i)) {
2884                 pic16_emitcode("dec","r0");
2885                 pic16_emitcode("movx","a,@r0");
2886                 if (i == R0_IDX)
2887                     pic16_emitcode("mov","b,a");
2888                 else
2889                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2890             }       
2891
2892         }
2893         pic16_emitcode("mov","%s,r0",spname);
2894         if (bitVectBitValue(rsave,R0_IDX))
2895             pic16_emitcode("mov","r0,b");
2896     } //else
2897     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2898     //    if (bitVectBitValue(rsave,i))
2899     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2900     //}
2901
2902 }  
2903 #endif
2904
2905 #if 0  // patch 14
2906 /*-----------------------------------------------------------------*/
2907 /* pushSide -                                                      */
2908 /*-----------------------------------------------------------------*/
2909 static void pushSide(operand * oper, int size)
2910 {
2911         int offset = 0;
2912     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2913         while (size--) {
2914                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2915                 if (AOP_TYPE(oper) != AOP_REG &&
2916                     AOP_TYPE(oper) != AOP_DIR &&
2917                     strcmp(l,"a") ) {
2918                         pic16_emitcode("mov","a,%s",l);
2919                         pic16_emitcode("push","acc");
2920                 } else
2921                         pic16_emitcode("push","%s",l);
2922         }
2923 }
2924 #endif // patch 14
2925
2926 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2927 {
2928   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2929     pic16_emitpcode(POC_MOVFW, src);
2930     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2931   } else {
2932     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2933         src, pic16_popGet(AOP(op), offset)));
2934   }
2935 }
2936
2937
2938 /*-----------------------------------------------------------------*/
2939 /* assignResultValue - assign results to oper, rescall==1 is       */
2940 /*                     called from genCall() or genPcall()         */
2941 /*-----------------------------------------------------------------*/
2942 static void assignResultValue(operand * oper, int rescall)
2943 {
2944   int size = AOP_SIZE(oper);
2945   int offset=0;
2946   
2947     FENTRY2;
2948 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2949     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2950
2951     if(rescall) {
2952       /* assign result from a call/pcall function() */
2953                 
2954       /* function results are stored in a special order,
2955        * see top of file with Function return policy, or manual */
2956
2957       if(size <= 4) {
2958         /* 8-bits, result in WREG */
2959         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2960                         
2961         if(size>1) {
2962           /* 16-bits, result in PRODL:WREG */
2963           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2964         }
2965                         
2966         if(size>2) {
2967           /* 24-bits, result in PRODH:PRODL:WREG */
2968           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2969         }
2970                         
2971         if(size>3) {
2972           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2973           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2974         }
2975       
2976       } else {
2977         /* >32-bits, result on stack, and FSR0 points to beginning.
2978          * Fix stack when done */
2979         /* FIXME FIXME */
2980 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2981         while (size--) {
2982 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2983 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2984                 
2985           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2986           GpsuedoStkPtr++;
2987         }
2988                         
2989         /* fix stack */
2990         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2991         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2992         if(STACK_MODEL_LARGE) {
2993           emitSKPNC;
2994           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2995         }
2996       }                 
2997     } else {
2998       int areg = 0;             /* matching argument register */
2999       
3000 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3001       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3002
3003
3004       /* its called from genReceive (probably) -- VR */
3005       /* I hope this code will not be called from somewhere else in the future! 
3006        * We manually set the pseudo stack pointer in genReceive. - dw
3007        */
3008       if(!GpsuedoStkPtr && _G.useWreg) {
3009 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3010
3011         /* The last byte in the assignment is in W */
3012         if(areg <= GpsuedoStkPtr) {
3013           size--;
3014           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3015           offset++;
3016 //          debugf("receive from WREG\n", 0);
3017         }
3018         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3019       }
3020 //      GpsuedoStkPtr++;
3021       _G.stack_lat = AOP_SIZE(oper)-1;
3022
3023       while (size) {
3024         size--;
3025         GpsuedoStkPtr++;
3026         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3027 //        debugf("receive from STACK\n", 0);
3028         offset++;
3029       }
3030     }
3031 }
3032
3033
3034 /*-----------------------------------------------------------------*/
3035 /* genIpush - generate code for pushing this gets a little complex */
3036 /*-----------------------------------------------------------------*/
3037 static void genIpush (iCode *ic)
3038 {
3039 //  int size, offset=0;
3040
3041   FENTRY;
3042   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3043
3044   if(ic->parmPush) {
3045     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3046
3047     /* send to stack as normal */
3048     addSet(&_G.sendSet,ic);
3049 //    addSetHead(&_G.sendSet,ic);
3050     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3051   }
3052
3053         
3054 #if 0
3055     int size, offset = 0 ;
3056     char *l;
3057
3058
3059     /* if this is not a parm push : ie. it is spill push 
3060     and spill push is always done on the local stack */
3061     if (!ic->parmPush) {
3062
3063         /* and the item is spilt then do nothing */
3064         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3065             return ;
3066
3067         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3068         size = AOP_SIZE(IC_LEFT(ic));
3069         /* push it on the stack */
3070         while(size--) {
3071             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3072             if (*l == '#') {
3073                 MOVA(l);
3074                 l = "acc";
3075             }
3076             pic16_emitcode("push","%s",l);
3077         }
3078         return ;        
3079     }
3080
3081     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3082 #endif
3083 }
3084
3085 /*-----------------------------------------------------------------*/
3086 /* genIpop - recover the registers: can happen only for spilling   */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpop (iCode *ic)
3089 {
3090   FENTRY;
3091   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3092 #if 0
3093     int size,offset ;
3094
3095
3096     /* if the temp was not pushed then */
3097     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3098         return ;
3099
3100     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3101     size = AOP_SIZE(IC_LEFT(ic));
3102     offset = (size-1);
3103     while (size--) 
3104         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3105                                    FALSE,TRUE));
3106
3107     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3108 #endif
3109 }
3110
3111 #if 0
3112 /*-----------------------------------------------------------------*/
3113 /* unsaverbank - restores the resgister bank from stack            */
3114 /*-----------------------------------------------------------------*/
3115 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3116 {
3117   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3118 #if 0
3119     int i;
3120     asmop *aop ;
3121     regs *r = NULL;
3122
3123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3124     if (popPsw) {
3125         if (options.useXstack) {
3126             aop = newAsmop(0);
3127             r = getFreePtr(ic,&aop,FALSE);
3128             
3129             
3130             pic16_emitcode("mov","%s,_spx",r->name);
3131             pic16_emitcode("movx","a,@%s",r->name);
3132             pic16_emitcode("mov","psw,a");
3133             pic16_emitcode("dec","%s",r->name);
3134             
3135         }else
3136             pic16_emitcode ("pop","psw");
3137     }
3138
3139     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3140         if (options.useXstack) {       
3141             pic16_emitcode("movx","a,@%s",r->name);
3142             //pic16_emitcode("mov","(%s+%d),a",
3143             //       regspic16[i].base,8*bank+regspic16[i].offset);
3144             pic16_emitcode("dec","%s",r->name);
3145
3146         } else 
3147           pic16_emitcode("pop",""); //"(%s+%d)",
3148         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3149     }
3150
3151     if (options.useXstack) {
3152
3153         pic16_emitcode("mov","_spx,%s",r->name);
3154         pic16_freeAsmop(NULL,aop,ic,TRUE);
3155
3156     }
3157 #endif 
3158 }
3159
3160 /*-----------------------------------------------------------------*/
3161 /* saverbank - saves an entire register bank on the stack          */
3162 /*-----------------------------------------------------------------*/
3163 static void saverbank (int bank, iCode *ic, bool pushPsw)
3164 {
3165   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3166 #if 0
3167     int i;
3168     asmop *aop ;
3169     regs *r = NULL;
3170
3171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3172     if (options.useXstack) {
3173
3174         aop = newAsmop(0);
3175         r = getFreePtr(ic,&aop,FALSE);  
3176         pic16_emitcode("mov","%s,_spx",r->name);
3177
3178     }
3179
3180     for (i = 0 ; i < pic16_nRegs ;i++) {
3181         if (options.useXstack) {
3182             pic16_emitcode("inc","%s",r->name);
3183             //pic16_emitcode("mov","a,(%s+%d)",
3184             //         regspic16[i].base,8*bank+regspic16[i].offset);
3185             pic16_emitcode("movx","@%s,a",r->name);           
3186         } else 
3187           pic16_emitcode("push","");// "(%s+%d)",
3188                      //regspic16[i].base,8*bank+regspic16[i].offset);
3189     }
3190     
3191     if (pushPsw) {
3192         if (options.useXstack) {
3193             pic16_emitcode("mov","a,psw");
3194             pic16_emitcode("movx","@%s,a",r->name);     
3195             pic16_emitcode("inc","%s",r->name);
3196             pic16_emitcode("mov","_spx,%s",r->name);       
3197             pic16_freeAsmop (NULL,aop,ic,TRUE);
3198             
3199         } else
3200             pic16_emitcode("push","psw");
3201         
3202         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3203     }
3204     ic->bankSaved = 1;
3205 #endif
3206 }
3207 #endif  /* 0 */
3208
3209
3210 static int wparamCmp(void *p1, void *p2)
3211 {
3212   return (!strcmp((char *)p1, (char *)p2));
3213 }
3214
3215 int inWparamList(char *s)
3216 {
3217   return isinSetWith(wparamList, s, wparamCmp);
3218
3219
3220
3221 /*-----------------------------------------------------------------*/
3222 /* genCall - generates a call statement                            */
3223 /*-----------------------------------------------------------------*/
3224 static void genCall (iCode *ic)
3225 {
3226   sym_link *ftype;   
3227   int stackParms=0;
3228   int use_wreg=0;
3229   int inwparam=0;
3230   char *fname;
3231   
3232     FENTRY;
3233
3234     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3235     /* if caller saves & we have not saved then */
3236 //    if (!ic->regsSaved)
3237 //      saveRegisters(ic);
3238
3239         /* initialise stackParms for IPUSH pushes */
3240 //      stackParms = psuedoStkPtr;
3241 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3242     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3243     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3244
3245 #if 0
3246     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3247 #endif
3248
3249     /* if send set is not empty the assign */
3250     if (_G.sendSet) {
3251       iCode *sic;
3252       int psuedoStkPtr=-1; 
3253       int firstTimeThruLoop = 1;
3254
3255
3256         /* reverse sendSet if function is not reentrant */
3257         if(!IFFUNC_ISREENT(ftype))
3258           _G.sendSet = reverseSet(_G.sendSet);
3259
3260         /* First figure how many parameters are getting passed */
3261         stackParms = 0;
3262         use_wreg = 0;
3263         
3264         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3265           int size;
3266 //          int offset = 0;
3267
3268             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3269             size = AOP_SIZE(IC_LEFT(sic));
3270
3271             stackParms += size;
3272
3273             /* pass the last byte through WREG */
3274             if(inwparam) {
3275
3276               while (size--) {
3277                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3278                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3279                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3280
3281                 if(!firstTimeThruLoop) {
3282                   /* If this is not the first time we've been through the loop
3283                    * then we need to save the parameter in a temporary
3284                    * register. The last byte of the last parameter is
3285                    * passed in W. */
3286
3287                   pushw();
3288 //                  --psuedoStkPtr;             // sanity check
3289                   use_wreg = 1;
3290                 }
3291                 
3292                 firstTimeThruLoop=0;
3293
3294                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3295
3296 //                offset++;
3297               }
3298             } else {
3299               /* all arguments are passed via stack */
3300               use_wreg = 0;
3301
3302               while (size--) {
3303                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3305                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3306
3307 //                pushaop(AOP(IC_LEFT(sic)), size);
3308                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3309                 pushw();
3310               }
3311             }
3312
3313             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3314           }
3315
3316           if(inwparam) {
3317             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3318               pushw();  /* save last parameter to stack if functions has varargs */
3319               use_wreg = 0;
3320             } else
3321               use_wreg = 1;
3322           } else use_wreg = 0;
3323
3324           _G.stackRegSet = _G.sendSet;
3325           _G.sendSet = NULL;
3326     }
3327
3328     /* make the call */
3329     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3330
3331     GpsuedoStkPtr=0;
3332     
3333     /* if we need to assign a result value */
3334     if ((IS_ITEMP(IC_RESULT(ic))
3335           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3336               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3337         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3338
3339       _G.accInUse++;
3340       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3341       _G.accInUse--;
3342
3343       assignResultValue(IC_RESULT(ic), 1);
3344
3345       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3347                 
3348       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3349     }
3350
3351     if(!stackParms && ic->parmBytes) {
3352       stackParms = ic->parmBytes;
3353     }
3354       
3355     stackParms -= use_wreg;
3356     
3357     if(stackParms>0) {
3358       if(stackParms == 1) {
3359         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3360       } else {
3361         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3362         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3363       }
3364       if(STACK_MODEL_LARGE) {
3365         emitSKPNC;
3366         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3367       }
3368     }
3369
3370 #if 0
3371     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3372 #endif
3373
3374     /* adjust the stack for parameters if required */
3375 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3376
3377 #if 0
3378       /* if register bank was saved then pop them */
3379       if (ic->bankSaved)
3380         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3381
3382       /* if we hade saved some registers then unsave them */
3383       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3384         unsaveRegisters (ic);
3385 #endif
3386 }
3387
3388
3389
3390 /*-----------------------------------------------------------------*/
3391 /* genPcall - generates a call by pointer statement                */
3392 /*            new version, created from genCall - HJD              */
3393 /*-----------------------------------------------------------------*/
3394 static void genPcall (iCode *ic)
3395 {
3396   sym_link *ftype, *fntype;
3397   int stackParms=0;
3398   symbol *retlbl = newiTempLabel(NULL);
3399   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3400   
3401     FENTRY;
3402
3403     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3404     fntype = operandType( IC_LEFT(ic) )->next;
3405
3406     /* if send set is not empty the assign */
3407     if (_G.sendSet) {
3408       iCode *sic;
3409       int psuedoStkPtr=-1; 
3410
3411       /* reverse sendSet if function is not reentrant */
3412       if(!IFFUNC_ISREENT(fntype))
3413         _G.sendSet = reverseSet(_G.sendSet);
3414
3415       stackParms = 0;
3416       
3417       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3418         int size;
3419
3420           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3421           size = AOP_SIZE(IC_LEFT(sic));
3422           stackParms += size;
3423
3424           /* all parameters are passed via stack, since WREG is clobbered
3425            * by the calling sequence */
3426           while (size--) {
3427             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3428             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3429             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3430
3431             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3432             pushw();
3433           }
3434
3435           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3436       }
3437
3438       _G.stackRegSet = _G.sendSet;
3439       _G.sendSet = NULL;
3440     }
3441
3442     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3443
3444     // push return address
3445     // push $ on return stack, then replace with retlbl
3446
3447     /* Thanks to Thorsten Klose for pointing out that the following
3448      * snippet should be interrupt safe */
3449     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3450     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3451
3452     pic16_emitpcodeNULLop(POC_PUSH);
3453
3454     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3455     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3456     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3457     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3458     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3459     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3460
3461
3462     /* restore interrupt control register */
3463     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3465
3466     /* make the call by writing the pointer into pc */
3467     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3468     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3469
3470     // note: MOVFF to PCL not allowed
3471     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3472     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3473
3474
3475     /* return address is here: (X) */
3476     pic16_emitpLabelFORCE(retlbl->key);
3477
3478     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3479
3480     GpsuedoStkPtr=0;
3481     /* if we need assign a result value */
3482     if ((IS_ITEMP(IC_RESULT(ic))
3483           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3484               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3485         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3486
3487       _G.accInUse++;
3488       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3489       _G.accInUse--;
3490
3491       assignResultValue(IC_RESULT(ic), 1);
3492
3493       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3494               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3495                 
3496       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3497     }
3498
3499 //    stackParms -= use_wreg;
3500     
3501     if(stackParms>0) {
3502       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3503       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3504       if(STACK_MODEL_LARGE) {
3505         emitSKPNC;
3506         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3507       }
3508     }
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* resultRemat - result  is rematerializable                       */
3513 /*-----------------------------------------------------------------*/
3514 static int resultRemat (iCode *ic)
3515 {
3516   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3517   if (SKIP_IC(ic) || ic->op == IFX)
3518     return 0;
3519
3520   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3521     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3522     if (sym->remat && !POINTER_SET(ic)) 
3523       return 1;
3524   }
3525
3526   return 0;
3527 }
3528
3529 #if defined(__BORLANDC__) || defined(_MSC_VER)
3530 #define STRCASECMP stricmp
3531 #else
3532 #define STRCASECMP strcasecmp
3533 #endif
3534
3535 #if 0
3536 /*-----------------------------------------------------------------*/
3537 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3538 /*-----------------------------------------------------------------*/
3539 static bool inExcludeList(char *s)
3540 {
3541   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3542     int i =0;
3543     
3544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545     if (options.excludeRegs[i] &&
3546     STRCASECMP(options.excludeRegs[i],"none") == 0)
3547         return FALSE ;
3548
3549     for ( i = 0 ; options.excludeRegs[i]; i++) {
3550         if (options.excludeRegs[i] &&
3551         STRCASECMP(s,options.excludeRegs[i]) == 0)
3552             return TRUE;
3553     }
3554     return FALSE ;
3555 }
3556 #endif
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genFunction - generated code for function entry                 */
3560 /*-----------------------------------------------------------------*/
3561 static void genFunction (iCode *ic)
3562 {
3563   symbol *sym;
3564   sym_link *ftype;
3565   
3566     FENTRY;
3567     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3568
3569     pic16_labelOffset += (max_key+4);
3570     max_key=0;
3571     GpsuedoStkPtr=0;
3572     _G.nRegsSaved = 0;
3573         
3574     ftype = operandType(IC_LEFT(ic));
3575     sym = OP_SYMBOL(IC_LEFT(ic));
3576
3577     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3578       /* create an absolute section at the interrupt vector:
3579        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3580       symbol *asym;
3581       char asymname[128];
3582       pBlock *apb;
3583
3584
3585 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3586
3587 #if 0
3588         {
3589           int i, found=-1;
3590
3591             sym = OP_SYMBOL( IC_LEFT(ic));
3592             for(i=0;i<=2;i++) {
3593               if(interrupts[i]->name
3594                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3595                   found = i;
3596                   break;
3597               }
3598             }
3599                         
3600             if(found == -1) {
3601               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3602                             __FILE__, __LINE__, sym->name);
3603 //              assert( 0 );
3604             }
3605             _G.interruptvector = found;
3606         }
3607 #endif
3608
3609         if(FUNC_INTNO(sym->type) == 256)
3610           sprintf(asymname, "ivec_%s", sym->name);
3611         else
3612           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3613         asym = newSymbol(asymname, 0);
3614
3615         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3616         pic16_addpBlock( apb );
3617
3618         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3619         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3620         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3621                 
3622         /* mark the end of this tiny function */
3623         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3624
3625         {
3626           absSym *abSym;
3627
3628             abSym = Safe_calloc(1, sizeof(absSym));
3629             strcpy(abSym->name, asymname);
3630
3631             switch( FUNC_INTNO(sym->type) ) {
3632               case 0: abSym->address = 0x000000; break;
3633               case 1: abSym->address = 0x000008; break;
3634               case 2: abSym->address = 0x000018; break;
3635               
3636               default:
3637                 abSym->address = -1; break;
3638             }
3639
3640             /* relocate interrupt vectors if needed */
3641             if(abSym->address != -1)
3642               abSym->address += pic16_options.ivt_loc;
3643
3644             addSet(&absSymSet, abSym);
3645         }
3646     }
3647
3648     /* create the function header */
3649     pic16_emitcode(";","-----------------------------------------");
3650     pic16_emitcode(";"," function %s",sym->name);
3651     pic16_emitcode(";","-----------------------------------------");
3652
3653     pic16_emitcode("","%s:",sym->rname);
3654     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3655
3656
3657     {
3658       absSym *ab;
3659
3660         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3661           if(!strcmp(ab->name, sym->rname)) {
3662             pic16_pBlockConvert2Absolute(pb);
3663             break;
3664           }
3665         }
3666     }
3667
3668
3669     if(IFFUNC_ISNAKED(ftype)) {
3670       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3671       return;
3672     }
3673         
3674     /* if critical function then turn interrupts off */
3675     if (IFFUNC_ISCRITICAL(ftype)) {
3676       //pic16_emitcode("clr","ea");
3677     }
3678
3679     _G.fregsUsed = sym->regsUsed;
3680
3681     /* if this is an interrupt service routine then
3682      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3683     if (IFFUNC_ISISR(sym->type)) {
3684         _G.usefastretfie = 1;   /* use shadow registers by default */
3685         
3686         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3687         if(!FUNC_ISSHADOWREGS(sym->type)) {
3688           /* do not save WREG,STATUS,BSR for high priority interrupts
3689            * because they are stored in the hardware shadow registers already */
3690           _G.usefastretfie = 0;
3691           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3692           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3693           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3694         }
3695
3696         /* these should really be optimized somehow, because not all
3697          * interrupt handlers modify them */
3698         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3699         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3701         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3702         
3703 //        pic16_pBlockConvert2ISR(pb);
3704                 
3705     }
3706
3707     /* emit code to setup stack frame if user enabled,
3708      * and function is not main() */
3709          
3710     //fprintf(stderr, "function name: %s\n", sym->name);
3711     if(strcmp(sym->name, "main")) {
3712       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3713         /* setup the stack frame */
3714         if(STACK_MODEL_LARGE)
3715           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3716         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3717
3718         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3719         if(STACK_MODEL_LARGE)
3720           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3721       }
3722     }
3723
3724     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3725           && sym->stack) {
3726
3727       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3728
3729       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3730       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3731       emitSKPC;
3732       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3733     }
3734           
3735     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3736       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3737         _G.useWreg = 0;
3738       else
3739         _G.useWreg = 1;
3740     } else
3741       _G.useWreg = 0;
3742
3743     /* if callee-save to be used for this function
3744      * then save the registers being used in this function */
3745 //    if (IFFUNC_CALLEESAVES(sym->type))
3746     {
3747       int i;
3748
3749         /* if any registers used */
3750         if (sym->regsUsed) {
3751           /* save the registers used */
3752           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3753           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3754           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3755             if (bitVectBitValue(sym->regsUsed,i)) {
3756               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3757               _G.nRegsSaved++;
3758
3759               if(!pic16_regWithIdx(i)->wasUsed) {
3760                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3761                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3762                 pic16_regWithIdx(i)->wasUsed = 1;
3763               }
3764             }
3765           }
3766           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3767         }
3768     }
3769         
3770     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3771 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3772 }
3773
3774 /*-----------------------------------------------------------------*/
3775 /* genEndFunction - generates epilogue for functions               */
3776 /*-----------------------------------------------------------------*/
3777 static void genEndFunction (iCode *ic)
3778 {
3779   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3780
3781     FENTRY;
3782
3783     if(IFFUNC_ISNAKED(sym->type)) {
3784       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3785       return;
3786     }
3787
3788     _G.stack_lat = 0;
3789
3790     /* add code for ISCRITICAL */
3791     if(IFFUNC_ISCRITICAL(sym->type)) {
3792       /* if critical function, turn on interrupts */
3793       
3794       /* TODO: add code here -- VR */
3795     }
3796     
3797 //    sym->regsUsed = _G.fregsUsed;
3798     
3799     /* now we need to restore the registers */
3800     /* if any registers used */
3801     if (sym->regsUsed) {
3802       int i;
3803
3804         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3805         /* restore registers used */
3806         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3807         for ( i = sym->regsUsed->size; i >= 0; i--) {
3808           if (bitVectBitValue(sym->regsUsed,i)) {
3809             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3810             _G.nRegsSaved--;
3811           }
3812         }
3813         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3814
3815     }
3816
3817     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3818           && sym->stack) {
3819       if (sym->stack == 1) {
3820         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3821         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3822       } else {
3823         // we have to add more than one...
3824         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3825         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3826         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3827         emitSKPNC;
3828         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3829         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3830         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3831       }
3832     }
3833
3834     if(strcmp(sym->name, "main")) {
3835       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3836         /* restore stack frame */
3837         if(STACK_MODEL_LARGE)
3838           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3839         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3840       }
3841     }
3842
3843     _G.useWreg = 0;
3844
3845     if (IFFUNC_ISISR(sym->type)) {
3846       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3847       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3848       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3849       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3850
3851       if(!FUNC_ISSHADOWREGS(sym->type)) {
3852         /* do not restore interrupt vector for WREG,STATUS,BSR
3853          * for high priority interrupt, see genFunction */
3854         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3855         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3856         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3857       }
3858 //      _G.interruptvector = 0;         /* sanity check */
3859
3860
3861       /* if debug then send end of function */
3862 /*      if (options.debug && currFunc)  */
3863       if (currFunc) {
3864         debugFile->writeEndFunction (currFunc, ic, 1);
3865       }
3866         
3867       if(_G.usefastretfie)
3868         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3869       else
3870         pic16_emitpcodeNULLop(POC_RETFIE);
3871
3872       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3873       
3874       _G.usefastretfie = 0;
3875       return;
3876     }
3877
3878     if (IFFUNC_ISCRITICAL(sym->type)) {
3879       pic16_emitcode("setb","ea");
3880     }
3881
3882     /* if debug then send end of function */
3883     if (currFunc) {
3884       debugFile->writeEndFunction (currFunc, ic, 1);
3885     }
3886
3887     /* insert code to restore stack frame, if user enabled it
3888      * and function is not main() */
3889          
3890
3891     pic16_emitpcodeNULLop(POC_RETURN);
3892
3893     /* Mark the end of a function */
3894     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3895 }
3896
3897
3898 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3899 {
3900   unsigned long lit=1;
3901  
3902   // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3903   if(AOP_TYPE(op) == AOP_LIT) {
3904     if(!IS_FLOAT(operandType( op ))) {
3905       lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3906     } else {
3907       union {
3908         unsigned long lit_int;
3909         float lit_float;
3910       } info;
3911         
3912       /* take care if literal is a float */
3913       info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3914       lit = info.lit_int;
3915     }
3916   }
3917
3918   if (is_LitOp(op)) {
3919       if(lit == 0) {
3920         pic16_emitpcode(POC_CLRF, dest);
3921       } else {
3922         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3923         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3924       }
3925   } else {
3926     if(dest->type == PO_WREG && (offset == 0)) {
3927       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3928       return;
3929     }
3930     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3931   }
3932 }
3933
3934 /*-----------------------------------------------------------------*/
3935 /* genRet - generate code for return statement                     */
3936 /*-----------------------------------------------------------------*/
3937 static void genRet (iCode *ic)
3938 {
3939   int size;
3940   operand *left;
3941
3942     FENTRY;
3943         /* if we have no return value then
3944          * just generate the "ret" */
3945         
3946         if (!IC_LEFT(ic)) 
3947                 goto jumpret;       
3948     
3949         /* we have something to return then
3950          * move the return value into place */
3951         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3952         size = AOP_SIZE(IC_LEFT(ic));
3953
3954         if(size <= 4) {
3955                 if(size>3) {
3956                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3957 //                      pic16_emitpcode(POC_MOVFF,
3958 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3959                 }
3960                 if(size>2) {
3961                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3962 //                      pic16_emitpcode(POC_MOVFF,
3963 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3964                 }
3965                 if(size>1) {
3966                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3967 //                      pic16_emitpcode(POC_MOVFF,
3968 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3969                 }
3970
3971 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3972
3973                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3974 //              pic16_emitpcode(POC_MOVFF,
3975 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3976
3977         } else {
3978                 /* >32-bits, setup stack and FSR0 */
3979                 while (size--) {
3980 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3981 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3982
3983                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3984
3985 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3986                         GpsuedoStkPtr++;
3987                 }
3988                         
3989                 /* setup FSR0 */
3990                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3991                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3992
3993                 if(STACK_MODEL_LARGE) {
3994                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3996                 } else {
3997                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3998                 }
3999         }
4000                                 
4001 #if 0
4002         /* old code, left here for reference -- VR */    
4003         while (size--) {
4004           char *l ;
4005
4006                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4007                         /* #NOCHANGE */
4008                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4009                         pic16_emitpcomment("push %s",l);
4010                         pushed++;
4011                 } else {
4012                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4013                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4014                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4015                         
4016                         if (strcmp(fReturn[offset],l)) {
4017                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4018                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4019                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4020                                 } else {
4021                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4022                                 }
4023                                 
4024                                 if(size) {
4025                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4026                                 }
4027                                 offset++;
4028                         }
4029                 }
4030         }    
4031
4032         if (pushed) {
4033                 while(pushed) {
4034                         pushed--;
4035                         if (strcmp(fReturn[pushed],"a"))
4036                                 pic16_emitcode("pop",fReturn[pushed]);
4037                         else
4038                                 pic16_emitcode("pop","acc");
4039                 }
4040         }
4041 #endif
4042
4043
4044         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4045     
4046 jumpret:
4047         /* generate a jump to the return label
4048          * if the next is not the return statement */
4049         if (!(ic->next && ic->next->op == LABEL
4050                 && IC_LABEL(ic->next) == returnLabel)) {
4051         
4052                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4053                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4054         }
4055 }
4056
4057 /*-----------------------------------------------------------------*/
4058 /* genLabel - generates a label                                    */
4059 /*-----------------------------------------------------------------*/
4060 static void genLabel (iCode *ic)
4061 {
4062   FENTRY;
4063
4064   /* special case never generate */
4065   if (IC_LABEL(ic) == entryLabel)
4066     return ;
4067
4068   pic16_emitpLabel(IC_LABEL(ic)->key);
4069 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4070 }
4071
4072 /*-----------------------------------------------------------------*/
4073 /* genGoto - generates a goto                                      */
4074 /*-----------------------------------------------------------------*/
4075 //tsd
4076 static void genGoto (iCode *ic)
4077 {
4078   FENTRY;
4079   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4080 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4081 }
4082
4083
4084 /*-----------------------------------------------------------------*/
4085 /* genMultbits :- multiplication of bits                           */
4086 /*-----------------------------------------------------------------*/
4087 static void genMultbits (operand *left, 
4088                          operand *right, 
4089                          operand *result)
4090 {
4091   FENTRY;
4092
4093   if(!pic16_sameRegs(AOP(result),AOP(right)))
4094     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4095
4096   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4097   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4098   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4099
4100 }
4101
4102
4103 /*-----------------------------------------------------------------*/
4104 /* genMultOneByte : 8 bit multiplication & division                */
4105 /*-----------------------------------------------------------------*/
4106 static void genMultOneByte (operand *left,
4107                             operand *right,
4108                             operand *result)
4109 {
4110
4111   FENTRY;
4112   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4113   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4114
4115   /* (if two literals, the value is computed before) */
4116   /* if one literal, literal on the right */
4117   if (AOP_TYPE(left) == AOP_LIT){
4118     operand *t = right;
4119     right = left;
4120     left = t;
4121   }
4122
4123         /* size is already checked in genMult == 1 */
4124 //      size = AOP_SIZE(result);
4125
4126         if (AOP_TYPE(right) == AOP_LIT){
4127                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4128                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4129                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4130                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4131         } else {
4132                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4133                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4134                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4136         }
4137         
4138         pic16_genMult8X8_8 (left, right,result);
4139 }
4140
4141 /*-----------------------------------------------------------------*/
4142 /* genMultOneWord : 16 bit multiplication                          */
4143 /*-----------------------------------------------------------------*/
4144 static void genMultOneWord (operand *left,
4145                             operand *right,
4146                             operand *result)
4147 {
4148   FENTRY;
4149   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4150   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4151
4152   /* (if two literals, the value is computed before)
4153    * if one literal, literal on the right */
4154   if (AOP_TYPE(left) == AOP_LIT){
4155     operand *t = right;
4156     right = left;
4157     left = t;
4158   }
4159
4160   /* size is checked already == 2 */
4161 //  size = AOP_SIZE(result);
4162
4163   if (AOP_TYPE(right) == AOP_LIT) {
4164     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4165       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4166       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4167       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4168   } else {
4169     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4170       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4171       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4173   }
4174         
4175   pic16_genMult16X16_16(left, right,result);
4176 }
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneLong : 32 bit multiplication                          */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneLong (operand *left,
4182                             operand *right,
4183                             operand *result)
4184 {
4185   FENTRY;
4186   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4187   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4188
4189   /* (if two literals, the value is computed before)
4190    * if one literal, literal on the right */
4191   if (AOP_TYPE(left) == AOP_LIT){
4192     operand *t = right;
4193     right = left;
4194     left = t;
4195   }
4196
4197   /* size is checked already == 4 */
4198 //  size = AOP_SIZE(result);
4199
4200   if (AOP_TYPE(right) == AOP_LIT) {
4201     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4202         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4203         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4204         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4205   } else {
4206     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4207         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4208         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210   }
4211         
4212   pic16_genMult32X32_32(left, right,result);
4213 }
4214
4215
4216
4217 /*-----------------------------------------------------------------*/
4218 /* genMult - generates code for multiplication                     */
4219 /*-----------------------------------------------------------------*/
4220 static void genMult (iCode *ic)
4221 {
4222   operand *left = IC_LEFT(ic);
4223   operand *right = IC_RIGHT(ic);
4224   operand *result= IC_RESULT(ic);   
4225
4226     FENTRY;
4227         /* assign the amsops */
4228         pic16_aopOp (left,ic,FALSE);
4229         pic16_aopOp (right,ic,FALSE);
4230         pic16_aopOp (result,ic,TRUE);
4231
4232         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4233
4234         /* special cases first *
4235         * both are bits */
4236         if (AOP_TYPE(left) == AOP_CRY
4237                 && AOP_TYPE(right)== AOP_CRY) {
4238                 genMultbits(left,right,result);
4239           goto release ;
4240         }
4241
4242         /* if both are of size == 1 */
4243         if(AOP_SIZE(left) == 1
4244                 && AOP_SIZE(right) == 1) {
4245                 genMultOneByte(left,right,result);
4246           goto release ;
4247         }
4248
4249         /* if both are of size == 2 */
4250         if(AOP_SIZE(left) == 2
4251                 && AOP_SIZE(right) == 2) {
4252                 genMultOneWord(left, right, result);
4253           goto release;
4254         }
4255         
4256         /* if both are of size == 4 */
4257         if(AOP_SIZE(left) == 4
4258                 && AOP_SIZE(right) == 4) {
4259                 genMultOneLong(left, right, result);
4260           goto release;
4261         }
4262         
4263         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4264
4265
4266         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4267         /* should have been converted to function call */
4268         assert(0) ;
4269
4270 release :
4271         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273         pic16_freeAsmop(result,NULL,ic,TRUE); 
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genDivbits :- division of bits                                  */
4278 /*-----------------------------------------------------------------*/
4279 static void genDivbits (operand *left, 
4280                         operand *right, 
4281                         operand *result)
4282 {
4283   char *l;
4284
4285     FENTRY;
4286     /* the result must be bit */    
4287     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4288     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4289
4290     MOVA(l);    
4291
4292     pic16_emitcode("div","ab");
4293     pic16_emitcode("rrc","a");
4294     pic16_aopPut(AOP(result),"c",0);
4295 }
4296
4297 /*-----------------------------------------------------------------*/
4298 /* genDivOneByte : 8 bit division                                  */
4299 /*-----------------------------------------------------------------*/
4300 static void genDivOneByte (operand *left,
4301                            operand *right,
4302                            operand *result)
4303 {
4304   sym_link *opetype = operandType(result);
4305   char *l ;
4306   symbol *lbl ;
4307   int size,offset;
4308
4309         /* result = divident / divisor
4310          * - divident may be a register or a literal,
4311          * - divisor may be a register or a literal,
4312          * so there are 3 cases (literal / literal is optimized
4313          * by the front-end) to handle.
4314          * In addition we must handle signed and unsigned, which
4315          * result in 6 final different cases -- VR */
4316
4317     FENTRY;
4318     
4319     size = AOP_SIZE(result) - 1;
4320     offset = 1;
4321     /* signed or unsigned */
4322     if (SPEC_USIGN(opetype)) {
4323       pCodeOp *pct1,    /* count */
4324                 *pct2,  /* reste */
4325                 *pct3;  /* temp */
4326       symbol *label1, *label2, *label3;;
4327
4328
4329         /* unsigned is easy */
4330
4331         pct1 = pic16_popGetTempReg(1);
4332         pct2 = pic16_popGetTempReg(1);
4333         pct3 = pic16_popGetTempReg(1);
4334         
4335         label1 = newiTempLabel(NULL);
4336         label2 = newiTempLabel(NULL);
4337         label3 = newiTempLabel(NULL);
4338
4339         /* the following algorithm is extracted from divuint.c */
4340
4341         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4342         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4343         
4344         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4345
4346         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4347         
4348         pic16_emitpLabel(label1->key);
4349         
4350         emitCLRC;
4351         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4352
4353
4354         emitCLRC;
4355         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4356         
4357
4358         emitSKPNC;
4359         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4360         
4361         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4362         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4363         
4364         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4365         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4366         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4367         
4368         pic16_emitpLabel( label3->key );
4369         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4370         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4371         
4372         
4373
4374         pic16_emitpLabel(label2->key);
4375         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4376         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4377         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4378         
4379         /* result is in wreg */
4380         if(AOP_TYPE(result) != AOP_ACC)
4381                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4382
4383         pic16_popReleaseTempReg( pct3, 1);
4384         pic16_popReleaseTempReg( pct2, 1);
4385         pic16_popReleaseTempReg( pct1, 1);
4386
4387         return ;
4388     }
4389
4390     /* signed is a little bit more difficult */
4391
4392     /* save the signs of the operands */
4393     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4394     MOVA(l);    
4395     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4396     pic16_emitcode("push","acc"); /* save it on the stack */
4397
4398     /* now sign adjust for both left & right */
4399     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4400     MOVA(l);       
4401     lbl = newiTempLabel(NULL);
4402     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4403     pic16_emitcode("cpl","a");   
4404     pic16_emitcode("inc","a");
4405     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4406     pic16_emitcode("mov","b,a");
4407
4408     /* sign adjust left side */
4409     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4410     MOVA(l);
4411
4412     lbl = newiTempLabel(NULL);
4413     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4414     pic16_emitcode("cpl","a");
4415     pic16_emitcode("inc","a");
4416     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417
4418     /* now the division */
4419     pic16_emitcode("div","ab");
4420     /* we are interested in the lower order
4421     only */
4422     pic16_emitcode("mov","b,a");
4423     lbl = newiTempLabel(NULL);
4424     pic16_emitcode("pop","acc");   
4425     /* if there was an over flow we don't 
4426     adjust the sign of the result */
4427     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4428     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4429     CLRC;
4430     pic16_emitcode("clr","a");
4431     pic16_emitcode("subb","a,b");
4432     pic16_emitcode("mov","b,a");
4433     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4434
4435     /* now we are done */
4436     pic16_aopPut(AOP(result),"b",0);
4437     if(size > 0){
4438         pic16_emitcode("mov","c,b.7");
4439         pic16_emitcode("subb","a,acc");   
4440     }
4441     while (size--)
4442         pic16_aopPut(AOP(result),"a",offset++);
4443
4444 }
4445
4446 /*-----------------------------------------------------------------*/
4447 /* genDiv - generates code for division                            */
4448 /*-----------------------------------------------------------------*/
4449 static void genDiv (iCode *ic)
4450 {
4451     operand *left = IC_LEFT(ic);
4452     operand *right = IC_RIGHT(ic);
4453     operand *result= IC_RESULT(ic);   
4454
4455
4456         /* Division is a very lengthy algorithm, so it is better
4457          * to call support routines than inlining algorithm.
4458          * Division functions written here just in case someone
4459          * wants to inline and not use the support libraries -- VR */
4460
4461     FENTRY;
4462     
4463     /* assign the amsops */
4464     pic16_aopOp (left,ic,FALSE);
4465     pic16_aopOp (right,ic,FALSE);
4466     pic16_aopOp (result,ic,TRUE);
4467
4468     /* special cases first */
4469     /* both are bits */
4470     if (AOP_TYPE(left) == AOP_CRY &&
4471         AOP_TYPE(right)== AOP_CRY) {
4472         genDivbits(left,right,result);
4473         goto release ;
4474     }
4475
4476     /* if both are of size == 1 */
4477     if (AOP_SIZE(left) == 1 &&
4478         AOP_SIZE(right) == 1 ) {
4479         genDivOneByte(left,right,result);
4480         goto release ;
4481     }
4482
4483     /* should have been converted to function call */
4484     assert(0);
4485 release :
4486     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     pic16_freeAsmop(result,NULL,ic,TRUE); 
4489 }
4490
4491 /*-----------------------------------------------------------------*/
4492 /* genModbits :- modulus of bits                                   */
4493 /*-----------------------------------------------------------------*/
4494 static void genModbits (operand *left, 
4495                         operand *right, 
4496                         operand *result)
4497 {
4498   char *l;
4499
4500     FENTRY;  
4501     
4502     werror(W_POSSBUG2, __FILE__, __LINE__);
4503     /* the result must be bit */    
4504     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4505     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4506
4507     MOVA(l);       
4508
4509     pic16_emitcode("div","ab");
4510     pic16_emitcode("mov","a,b");
4511     pic16_emitcode("rrc","a");
4512     pic16_aopPut(AOP(result),"c",0);
4513 }
4514
4515 /*-----------------------------------------------------------------*/
4516 /* genModOneByte : 8 bit modulus                                   */
4517 /*-----------------------------------------------------------------*/
4518 static void genModOneByte (operand *left,
4519                            operand *right,
4520                            operand *result)
4521 {
4522   sym_link *opetype = operandType(result);
4523   char *l ;
4524   symbol *lbl ;
4525
4526     FENTRY;
4527     werror(W_POSSBUG2, __FILE__, __LINE__);
4528
4529     /* signed or unsigned */
4530     if (SPEC_USIGN(opetype)) {
4531         /* unsigned is easy */
4532         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4534         MOVA(l);    
4535         pic16_emitcode("div","ab");
4536         pic16_aopPut(AOP(result),"b",0);
4537         return ;
4538     }
4539
4540     /* signed is a little bit more difficult */
4541
4542     /* save the signs of the operands */
4543     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4544     MOVA(l);
4545
4546     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4547     pic16_emitcode("push","acc"); /* save it on the stack */
4548
4549     /* now sign adjust for both left & right */
4550     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4551     MOVA(l);
4552
4553     lbl = newiTempLabel(NULL);
4554     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4555     pic16_emitcode("cpl","a");   
4556     pic16_emitcode("inc","a");
4557     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4558     pic16_emitcode("mov","b,a"); 
4559
4560     /* sign adjust left side */
4561     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4562     MOVA(l);
4563
4564     lbl = newiTempLabel(NULL);
4565     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4566     pic16_emitcode("cpl","a");   
4567     pic16_emitcode("inc","a");
4568     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4569
4570     /* now the multiplication */
4571     pic16_emitcode("div","ab");
4572     /* we are interested in the lower order
4573     only */
4574     lbl = newiTempLabel(NULL);
4575     pic16_emitcode("pop","acc");   
4576     /* if there was an over flow we don't 
4577     adjust the sign of the result */
4578     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4579     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4580     CLRC ;
4581     pic16_emitcode("clr","a");
4582     pic16_emitcode("subb","a,b");
4583     pic16_emitcode("mov","b,a");
4584     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4585
4586     /* now we are done */
4587     pic16_aopPut(AOP(result),"b",0);
4588
4589 }
4590
4591 /*-----------------------------------------------------------------*/
4592 /* genMod - generates code for division                            */
4593 /*-----------------------------------------------------------------*/
4594 static void genMod (iCode *ic)
4595 {
4596   operand *left = IC_LEFT(ic);
4597   operand *right = IC_RIGHT(ic);
4598   operand *result= IC_RESULT(ic);  
4599
4600     FENTRY;
4601     
4602     /* assign the amsops */
4603     pic16_aopOp (left,ic,FALSE);
4604     pic16_aopOp (right,ic,FALSE);
4605     pic16_aopOp (result,ic,TRUE);
4606
4607     /* special cases first */
4608     /* both are bits */
4609     if (AOP_TYPE(left) == AOP_CRY &&
4610         AOP_TYPE(right)== AOP_CRY) {
4611         genModbits(left,right,result);
4612         goto release ;
4613     }
4614
4615     /* if both are of size == 1 */
4616     if (AOP_SIZE(left) == 1 &&
4617         AOP_SIZE(right) == 1 ) {
4618         genModOneByte(left,right,result);
4619         goto release ;
4620     }
4621
4622     /* should have been converted to function call */
4623     assert(0);
4624
4625 release :
4626     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(result,NULL,ic,TRUE); 
4629 }
4630
4631 /*-----------------------------------------------------------------*/
4632 /* genIfxJump :- will create a jump depending on the ifx           */
4633 /*-----------------------------------------------------------------*/
4634 /*
4635   note: May need to add parameter to indicate when a variable is in bit space.
4636 */
4637 static void genIfxJump (iCode *ic, char *jval)
4638 {
4639   FENTRY;
4640   
4641     /* if true label then we jump if condition
4642     supplied is true */
4643     if ( IC_TRUE(ic) ) {
4644
4645         if(strcmp(jval,"a") == 0)
4646           emitSKPZ;
4647         else if (strcmp(jval,"c") == 0)
4648           emitSKPNC;
4649         else {
4650           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4651           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4652         }
4653
4654         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4655         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4656
4657     }
4658     else {
4659         /* false label is present */
4660         if(strcmp(jval,"a") == 0)
4661           emitSKPNZ;
4662         else if (strcmp(jval,"c") == 0)
4663           emitSKPC;
4664         else {
4665           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4666           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4667         }
4668
4669         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4670         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4671
4672     }
4673
4674
4675     /* mark the icode as generated */
4676     ic->generated = 1;
4677 }
4678
4679 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4680 {
4681   FENTRY;
4682   
4683     /* if true label then we jump if condition
4684     supplied is true */
4685     if ( IC_TRUE(ic) ) {
4686       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4687       pic16_emitpcode(POC_BTFSC, jop);
4688
4689       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4690       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4691
4692     } else {
4693       /* false label is present */
4694       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4695       pic16_emitpcode(POC_BTFSS, jop);
4696           
4697       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4698       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4699     }
4700
4701
4702     /* mark the icode as generated */
4703     ic->generated = 1;
4704 }
4705
4706 #if 0
4707 // not needed ATM
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genSkip                                                         */
4711 /*-----------------------------------------------------------------*/
4712 static void genSkip(iCode *ifx,int status_bit)
4713 {
4714   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4715   if(!ifx)
4716     return;
4717
4718   if ( IC_TRUE(ifx) ) {
4719     switch(status_bit) {
4720     case 'z':
4721       emitSKPNZ;
4722       break;
4723
4724     case 'c':
4725       emitSKPNC;
4726       break;
4727
4728     case 'd':
4729       emitSKPDC;
4730       break;
4731
4732     }
4733
4734     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4735     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4736
4737   } else {
4738
4739     switch(status_bit) {
4740
4741     case 'z':
4742       emitSKPZ;
4743       break;
4744
4745     case 'c':
4746       emitSKPC;
4747       break;
4748
4749     case 'd':
4750       emitSKPDC;
4751       break;
4752     }
4753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4754     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4755
4756   }
4757
4758 }
4759 #endif
4760
4761 /*-----------------------------------------------------------------*/
4762 /* genSkipc                                                        */
4763 /*-----------------------------------------------------------------*/
4764 static void genSkipc(resolvedIfx *rifx)
4765 {
4766   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4767   
4768   if(!rifx)
4769     return;
4770
4771   if(rifx->condition)
4772     emitSKPC;
4773   else
4774     emitSKPNC;
4775
4776   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4777   rifx->generated = 1;
4778 }
4779
4780 #if !(USE_SIMPLE_GENCMP)
4781 /*-----------------------------------------------------------------*/
4782 /* genSkipz2                                                       */
4783 /*-----------------------------------------------------------------*/
4784 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4785 {
4786   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4787   
4788   if(!rifx)
4789     return;
4790
4791   if( (rifx->condition ^ invert_condition) & 1)
4792     emitSKPZ;
4793   else
4794     emitSKPNZ;
4795
4796   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797   rifx->generated = 1;
4798 }
4799 #endif
4800
4801 #if 0
4802 /*-----------------------------------------------------------------*/
4803 /* genSkipz                                                        */
4804 /*-----------------------------------------------------------------*/
4805 static void genSkipz(iCode *ifx, int condition)
4806 {
4807   if(!ifx)
4808     return;
4809
4810   if(condition)
4811     emitSKPNZ;
4812   else
4813     emitSKPZ;
4814
4815   if ( IC_TRUE(ifx) )
4816     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4817   else
4818     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4819
4820   if ( IC_TRUE(ifx) )
4821     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4822   else
4823     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4824
4825 }
4826 #endif
4827
4828 #if !(USE_SIMPLE_GENCMP)
4829 /*-----------------------------------------------------------------*/
4830 /* genSkipCond                                                     */
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4833 {
4834   if(!rifx)
4835     return;
4836
4837   if(rifx->condition)
4838     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4839   else
4840     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4841
4842
4843   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4844   rifx->generated = 1;
4845 }
4846 #endif
4847
4848 #if 0
4849 /*-----------------------------------------------------------------*/
4850 /* genChkZeroes :- greater or less than comparison                 */
4851 /*     For each byte in a literal that is zero, inclusive or the   */
4852 /*     the corresponding byte in the operand with W                */
4853 /*     returns true if any of the bytes are zero                   */
4854 /*-----------------------------------------------------------------*/
4855 static int genChkZeroes(operand *op, int lit,  int size)
4856 {
4857
4858   int i;
4859   int flag =1;
4860
4861   while(size--) {
4862     i = (lit >> (size*8)) & 0xff;
4863
4864     if(i==0) {
4865       if(flag) 
4866         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4867       else
4868         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4869       flag = 0;
4870     }
4871   }
4872
4873   return (flag==0);
4874 }
4875 #endif
4876
4877 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4878 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4879 #endif
4880 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4881 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4882
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4885 /*                  aop (if it's NOT a literal) or from lit (if    */
4886 /*                  aop is a literal)                              */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889   if (aop->type == AOP_LIT) {
4890     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4891   } else {
4892     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4893   }
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison                       */
4898 /*-----------------------------------------------------------------*/
4899
4900 #if USE_SIMPLE_GENCMP
4901
4902 /* genCmp performs a left < right comparison, stores
4903  * the outcome in result (if != NULL) and generates
4904  * control flow code for the ifx (if != NULL).
4905  *
4906  * This version leaves in sequences like
4907  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908  * which should be optmized by the peephole
4909  * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911                     operand *result, iCode *ifx, int sign)
4912 {
4913   resolvedIfx rIfx;
4914   int size;
4915   int offs;
4916   symbol *templbl;
4917   operand *dummy;
4918   unsigned long lit;
4919   unsigned long mask;
4920   int performedLt;
4921
4922   FENTRY;
4923   
4924   assert (AOP_SIZE(left) == AOP_SIZE(right));
4925   assert (left && right);
4926
4927   size = AOP_SIZE(right) - 1;
4928   mask = (0x100UL << (size*8)) - 1;
4929   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4930   performedLt = 1;
4931   templbl = NULL;
4932   lit = 0;
4933   
4934   resolveIfx (&rIfx, ifx);
4935
4936   /**********************************************************************
4937    * handle bits - bit compares are promoted to int compares seemingly! *
4938    **********************************************************************/
4939 #if 0
4940   // THIS IS COMPLETELY UNTESTED!
4941   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4945
4946     emitSETC;
4947     // 1 < {0,1} is false --> clear C by skipping the next instruction
4948     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952     emitCLRC; // only skipped for left=0 && right=1
4953
4954     goto correct_result_in_carry;
4955   } // if
4956 #endif
4957
4958   /*************************************************
4959    * make sure that left is register (or the like) *
4960    *************************************************/
4961   if (!isAOP_REGlike(left)) {
4962     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4963     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4964     #endif
4965     assert (isAOP_LIT(left));
4966     assert (isAOP_REGlike(right));
4967     // swap left and right
4968     // left < right <==> right > left <==> (right >= left + 1)
4969     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4970
4971     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4972       // MAXVALUE < right? always false
4973       if (performedLt) emitCLRC; else emitSETC;
4974       goto correct_result_in_carry;
4975     } // if
4976
4977     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4978     // that's we handled it above.
4979     lit++;
4980
4981     dummy = left;
4982     left = right;
4983     right = dummy;
4984
4985     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4986   } else if (isAOP_LIT(right)) {
4987     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4988   } // if
4989
4990   assert (isAOP_REGlike(left)); // left must be register or the like
4991   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4992
4993   /*************************************************
4994    * special cases go here                         *
4995    *************************************************/
4996
4997   if (isAOP_LIT(right)) {
4998     if (!sign) {
4999       // unsigned comparison to a literal
5000       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5001       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5002       #endif
5003       if (lit == 0) {
5004         // unsigned left < 0? always false
5005         if (performedLt) emitCLRC; else emitSETC;
5006         goto correct_result_in_carry;
5007       }
5008     } else {
5009       // signed comparison to a literal
5010       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5011       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5012       #endif
5013       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5014         // signed left < 0x80000000? always false
5015         if (performedLt) emitCLRC; else emitSETC;
5016         goto correct_result_in_carry;
5017       } else if (lit == 0) {
5018         // compare left < 0; set CARRY if SIGNBIT(left) is set
5019         if (performedLt) emitSETC; else emitCLRC;
5020         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5021         if (performedLt) emitCLRC; else emitSETC;
5022         goto correct_result_in_carry;
5023       }
5024     } // if (!sign)
5025   } // right is literal
5026
5027   /*************************************************
5028    * perform a general case comparison             *
5029    * make sure we get CARRY==1 <==> left >= right  *
5030    *************************************************/
5031   // compare most significant bytes
5032   //DEBUGpc ("comparing bytes at offset %d", size);
5033   if (!sign) {
5034     // unsigned comparison
5035     mov2w_regOrLit (AOP(right), lit, size);
5036     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5037   } else {
5038     // signed comparison
5039     // (add 2^n to both operands then perform an unsigned comparison)
5040     if (isAOP_LIT(right)) {
5041       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5042       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5043
5044       if (litbyte == 0x80) {
5045         // left >= 0x80 -- always true, but more bytes to come
5046         pic16_mov2w (AOP(left), size);
5047         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5048         emitSETC;
5049       } else {
5050         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5051         pic16_mov2w (AOP(left), size);
5052         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5053         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5054       } // if
5055     } else {
5056       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058       pic16_mov2w (AOP(left), size);
5059       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060       pic16_emitpcode (POC_MOVWF, pctemp);
5061       pic16_mov2w (AOP(right), size);
5062       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063       pic16_emitpcode (POC_SUBFW, pctemp);
5064       //pic16_popReleaseTempReg(pctemp, 1);
5065     }
5066   } // if (!sign)
5067
5068   // compare remaining bytes (treat as unsigned case from above)
5069   templbl = newiTempLabel ( NULL );
5070   offs = size;
5071   while (offs--) {
5072     //DEBUGpc ("comparing bytes at offset %d", offs);
5073     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074     mov2w_regOrLit (AOP(right), lit, offs);
5075     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5076   } // while (offs)
5077   pic16_emitpLabel (templbl->key);
5078   goto result_in_carry;
5079
5080 result_in_carry:
5081   
5082   /****************************************************
5083    * now CARRY contains the result of the comparison: *
5084    * SUBWF sets CARRY iff                             *
5085    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5086    * (F=left, W=right)
5087    ****************************************************/
5088
5089   if (performedLt) {
5090     if (result && AOP_TYPE(result) != AOP_CRY) {
5091       // value will be stored
5092       emitTOGC;
5093     } else {
5094       // value wil only be used in the following genSkipc()
5095       rIfx.condition ^= 1;
5096     }
5097   } // if
5098
5099 correct_result_in_carry:
5100
5101   // assign result to variable (if neccessary)
5102   if (result && AOP_TYPE(result) != AOP_CRY) {
5103     //DEBUGpc ("assign result");
5104     size = AOP_SIZE(result);
5105     while (size--) {
5106       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5107     } // while
5108     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5109   } // if (result)
5110
5111   // perform conditional jump
5112   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5113   if (ifx) {
5114     //DEBUGpc ("generate control flow");
5115     rIfx.condition ^= 1;
5116     genSkipc (&rIfx);
5117     ifx->generated = 1;
5118   } // if
5119 }
5120
5121 #elif 1
5122                 /* { */
5123       /* original code */
5124 static void genCmp (operand *left,operand *right,
5125                     operand *result, iCode *ifx, int sign)
5126 {
5127   int size; //, offset = 0 ;
5128   unsigned long lit = 0L,i = 0;
5129   resolvedIfx rFalseIfx;
5130   //  resolvedIfx rTrueIfx;
5131   symbol *truelbl;
5132   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5133 /*
5134   if(ifx) {
5135     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5136     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5137   }
5138 */
5139
5140   FENTRY;
5141   
5142   resolveIfx(&rFalseIfx,ifx);
5143   truelbl  = newiTempLabel(NULL);
5144   size = max(AOP_SIZE(left),AOP_SIZE(right));
5145
5146   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5147
5148 #define _swapp
5149
5150   /* if literal is on the right then swap with left */
5151   if ((AOP_TYPE(right) == AOP_LIT)) {
5152     operand *tmp = right ;
5153     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5154     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5155 #ifdef _swapp
5156
5157     lit = (lit - 1) & mask;
5158     right = left;
5159     left = tmp;
5160     rFalseIfx.condition ^= 1;
5161 #endif
5162
5163   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5164     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5165   }
5166
5167
5168   //if(IC_TRUE(ifx) == NULL)
5169   /* if left & right are bit variables */
5170   if (AOP_TYPE(left) == AOP_CRY &&
5171       AOP_TYPE(right) == AOP_CRY ) {
5172     assert (0 && "bit variables used in genCmp");
5173     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5174     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5175   } else {
5176     /* subtract right from left if at the
5177        end the carry flag is set then we know that
5178        left is greater than right */
5179
5180     symbol *lbl  = newiTempLabel(NULL);
5181
5182 #if 0
5183         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5184                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5185 #endif
5186
5187 #ifndef _swapp
5188     if(AOP_TYPE(right) == AOP_LIT) {
5189
5190       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5191
5192       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5193
5194       /* special cases */
5195
5196       if(lit == 0) {
5197
5198         if(sign != 0) 
5199           genSkipCond(&rFalseIfx,left,size-1,7);
5200         else 
5201           /* no need to compare to 0...*/
5202           /* NOTE: this is a de-generate compare that most certainly 
5203            *       creates some dead code. */
5204           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5205
5206         if(ifx) ifx->generated = 1;
5207         return;
5208
5209       }
5210       size--;
5211
5212       if(size == 0) {
5213         //i = (lit >> (size*8)) & 0xff;
5214         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5215         
5216         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5217
5218         i = ((0-lit) & 0xff);
5219         if(sign) {
5220           if( i == 0x81) { 
5221             /* lit is 0x7f, all signed chars are less than
5222              * this except for 0x7f itself */
5223             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5224             genSkipz2(&rFalseIfx,0);
5225           } else {
5226             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5227             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5228             genSkipc(&rFalseIfx);
5229           }
5230
5231         } else {
5232           if(lit == 1) {
5233             genSkipz2(&rFalseIfx,1);
5234           } else {
5235             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5236             genSkipc(&rFalseIfx);
5237           }
5238         }
5239
5240         if(ifx) ifx->generated = 1;
5241         return;
5242       }
5243
5244       /* chars are out of the way. now do ints and longs */
5245
5246
5247       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5248         
5249       /* special cases */
5250
5251       if(sign) {
5252
5253         if(lit == 0) {
5254           genSkipCond(&rFalseIfx,left,size,7);
5255           if(ifx) ifx->generated = 1;
5256           return;
5257         }
5258
5259         if(lit <0x100) {
5260           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5261
5262           //rFalseIfx.condition ^= 1;
5263           //genSkipCond(&rFalseIfx,left,size,7);
5264           //rFalseIfx.condition ^= 1;
5265
5266           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5267           if(rFalseIfx.condition)
5268             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5269           else
5270             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5271
5272           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5273           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5274           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5275
5276           while(size > 1)
5277             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5278
5279           if(rFalseIfx.condition) {
5280             emitSKPZ;
5281             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5282
5283           } else {
5284             emitSKPNZ;
5285           }
5286
5287           genSkipc(&rFalseIfx);
5288           pic16_emitpLabel(truelbl->key);
5289           if(ifx) ifx->generated = 1;
5290           return;
5291
5292         }
5293
5294         if(size == 1) {
5295
5296           if( (lit & 0xff) == 0) {
5297             /* lower byte is zero */
5298             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5299             i = ((lit >> 8) & 0xff) ^0x80;
5300             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5301             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5302             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5303             genSkipc(&rFalseIfx);
5304
5305
5306             if(ifx) ifx->generated = 1;
5307             return;
5308
5309           }
5310         } else {
5311           /* Special cases for signed longs */
5312           if( (lit & 0xffffff) == 0) {
5313             /* lower byte is zero */
5314             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5315             i = ((lit >> 8*3) & 0xff) ^0x80;
5316             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5317             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5319             genSkipc(&rFalseIfx);
5320
5321
5322             if(ifx) ifx->generated = 1;
5323             return;
5324
5325           }
5326
5327         }
5328
5329
5330         if(lit & (0x80 << (size*8))) {
5331           /* lit is negative */
5332           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5333
5334           //genSkipCond(&rFalseIfx,left,size,7);
5335
5336           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5337
5338           if(rFalseIfx.condition)
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5340           else
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342
5343
5344         } else {
5345           /* lit is positive */
5346           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5347           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5348           if(rFalseIfx.condition)
5349             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5350           else
5351             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5352
5353         }
5354
5355         /*
5356           This works, but is only good for ints.
5357           It also requires a "known zero" register.
5358           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5359           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5361           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5362           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5363           genSkipc(&rFalseIfx);
5364
5365           pic16_emitpLabel(truelbl->key);
5366           if(ifx) ifx->generated = 1;
5367           return;
5368         **/
5369           
5370         /* There are no more special cases, so perform a general compare */
5371   
5372         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5373         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374
5375         while(size--) {
5376
5377           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5378           emitSKPNZ;
5379           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5380         }
5381         //rFalseIfx.condition ^= 1;
5382         genSkipc(&rFalseIfx);
5383
5384         pic16_emitpLabel(truelbl->key);
5385
5386         if(ifx) ifx->generated = 1;
5387         return;
5388
5389
5390       }
5391
5392
5393       /* sign is out of the way. So now do an unsigned compare */
5394       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5395
5396
5397       /* General case - compare to an unsigned literal on the right.*/
5398
5399       i = (lit >> (size*8)) & 0xff;
5400       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5402       while(size--) {
5403         i = (lit >> (size*8)) & 0xff;
5404
5405         if(i) {
5406           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5407           emitSKPNZ;
5408           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5409         } else {
5410           /* this byte of the lit is zero, 
5411            *if it's not the last then OR in the variable */
5412           if(size)
5413             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5414         }
5415       }
5416
5417
5418       pic16_emitpLabel(lbl->key);
5419 //      pic16_emitpLabel(truelbl->key);
5420       //if(emitFinalCheck)
5421       genSkipc(&rFalseIfx);
5422       if(sign)
5423         pic16_emitpLabel(truelbl->key);
5424
5425       if(ifx) ifx->generated = 1;
5426       return;
5427
5428
5429     }
5430 #endif  // _swapp
5431
5432     if(AOP_TYPE(left) == AOP_LIT) {
5433       //symbol *lbl = newiTempLabel(NULL);
5434
5435       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5436
5437
5438       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5439
5440       /* Special cases */
5441       if((lit == 0) && (sign == 0)){
5442
5443         size--;
5444         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5445         while(size) 
5446           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5447
5448         genSkipz2(&rFalseIfx,0);
5449         if(ifx) ifx->generated = 1;
5450         return;
5451       }
5452
5453       if(size==1) {
5454         /* Special cases */
5455         lit &= 0xff;
5456         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5457           /* degenerate compare can never be true */
5458           if(rFalseIfx.condition == 0)
5459             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5460
5461           if(ifx) ifx->generated = 1;
5462           return;
5463         }
5464
5465         if(sign) {
5466           /* signed comparisons to a literal byte */
5467
5468           int lp1 = (lit+1) & 0xff;
5469
5470           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5471           switch (lp1) {
5472           case 0:
5473             rFalseIfx.condition ^= 1;
5474             genSkipCond(&rFalseIfx,right,0,7);
5475             break;
5476           case 0x7f:
5477             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5479             genSkipz2(&rFalseIfx,1);
5480             break;
5481           default:
5482             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5483             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5484             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5485             rFalseIfx.condition ^= 1;
5486             genSkipc(&rFalseIfx);
5487             break;
5488           }
5489         } else {
5490           /* unsigned comparisons to a literal byte */
5491
5492           switch(lit & 0xff ) {
5493           case 0:
5494             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5495             genSkipz2(&rFalseIfx,0);
5496             break;
5497           case 0x7f:
5498             rFalseIfx.condition ^= 1;
5499             genSkipCond(&rFalseIfx,right,0,7);
5500             break;
5501
5502           default:
5503             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5504             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5505             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5506             rFalseIfx.condition ^= 1;
5507             if (AOP_TYPE(result) == AOP_CRY)
5508               genSkipc(&rFalseIfx);
5509             else {
5510               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5511               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5512             }         
5513             break;
5514           }
5515         }
5516
5517         if(ifx) ifx->generated = 1;
5518         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5519                 goto check_carry;
5520         return;
5521
5522       } else {
5523
5524         /* Size is greater than 1 */
5525
5526         if(sign) {
5527           int lp1 = lit+1;
5528
5529           size--;
5530
5531           if(lp1 == 0) {
5532             /* this means lit = 0xffffffff, or -1 */
5533
5534
5535             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5536             rFalseIfx.condition ^= 1;
5537             genSkipCond(&rFalseIfx,right,size,7);
5538             if(ifx) ifx->generated = 1;
5539
5540             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5541               goto check_carry;
5542
5543             return;
5544           }
5545
5546           if(lit == 0) {
5547             int s = size;
5548
5549             if(rFalseIfx.condition) {
5550               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5551               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5552             }
5553
5554             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555             while(size--)
5556               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5557
5558
5559             emitSKPZ;
5560             if(rFalseIfx.condition) {
5561               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5562               pic16_emitpLabel(truelbl->key);
5563             }else {
5564               rFalseIfx.condition ^= 1;
5565               genSkipCond(&rFalseIfx,right,s,7);
5566             }
5567
5568             if(ifx) ifx->generated = 1;
5569
5570             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5571               goto check_carry;
5572
5573             return;
5574           }
5575
5576           if((size == 1) &&  (0 == (lp1&0xff))) {
5577             /* lower byte of signed word is zero */
5578             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5579             i = ((lp1 >> 8) & 0xff) ^0x80;
5580             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5581             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5582             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5583
5584             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5585               emitTOGC;
5586               if(ifx) ifx->generated = 1;
5587               goto check_carry;
5588             } else {
5589               rFalseIfx.condition ^= 1;
5590               genSkipc(&rFalseIfx);
5591               if(ifx) ifx->generated = 1;
5592             }
5593
5594             return;
5595           }
5596
5597           if(lit & (0x80 << (size*8))) {
5598             /* Lit is less than zero */
5599             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5600             //rFalseIfx.condition ^= 1;
5601             //genSkipCond(&rFalseIfx,left,size,7);
5602             //rFalseIfx.condition ^= 1;
5603             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5604             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5605
5606             if(rFalseIfx.condition)
5607               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5608             else
5609               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5610
5611
5612           } else {
5613             /* Lit is greater than or equal to zero */
5614             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5615             //rFalseIfx.condition ^= 1;
5616             //genSkipCond(&rFalseIfx,right,size,7);
5617             //rFalseIfx.condition ^= 1;
5618
5619             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5620             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5621
5622             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5623             if(rFalseIfx.condition)
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             else
5626               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5627
5628           }
5629
5630           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5631           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5632
5633           while(size--) {
5634
5635             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5636             emitSKPNZ;
5637             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5638           }
5639           rFalseIfx.condition ^= 1;
5640           //rFalseIfx.condition = 1;
5641           genSkipc(&rFalseIfx);
5642
5643           pic16_emitpLabel(truelbl->key);
5644
5645           if(ifx) ifx->generated = 1;
5646
5647
5648           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649             goto check_carry;
5650
5651           return;
5652           // end of if (sign)
5653         } else {
5654
5655           /* compare word or long to an unsigned literal on the right.*/
5656
5657
5658           size--;
5659           if(lit < 0xff) {
5660             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5661             switch (lit) {
5662             case 0:
5663               break; /* handled above */
5664 /*
5665             case 0xff:
5666               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5667               while(size--)
5668                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5669               genSkipz2(&rFalseIfx,0);
5670               break;
5671 */
5672             default:
5673               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5674               while(--size)
5675                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5676
5677               emitSKPZ;
5678               if(rFalseIfx.condition)
5679                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5680               else
5681                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5682
5683
5684               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5685               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5686
5687               rFalseIfx.condition ^= 1;
5688               genSkipc(&rFalseIfx);
5689             }
5690
5691             pic16_emitpLabel(truelbl->key);
5692
5693             if(ifx) ifx->generated = 1;
5694
5695             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5696               goto check_carry;
5697
5698             return;
5699           }
5700
5701
5702           lit++;
5703           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5704           i = (lit >> (size*8)) & 0xff;
5705
5706           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5707           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708
5709           while(size--) {
5710             i = (lit >> (size*8)) & 0xff;
5711
5712             if(i) {
5713               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5714               emitSKPNZ;
5715               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5716             } else {
5717               /* this byte of the lit is zero, 
5718                * if it's not the last then OR in the variable */
5719               if(size)
5720                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5721             }
5722           }
5723
5724
5725           pic16_emitpLabel(lbl->key);
5726
5727           rFalseIfx.condition ^= 1;
5728
5729           genSkipc(&rFalseIfx);
5730         }
5731
5732         if(sign)
5733           pic16_emitpLabel(truelbl->key);
5734         if(ifx) ifx->generated = 1;
5735
5736             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5737               goto check_carry;
5738
5739         return;
5740       }
5741     }
5742     /* Compare two variables */
5743
5744     DEBUGpic16_emitcode(";sign","%d",sign);
5745
5746     size--;
5747     if(sign) {
5748       /* Sigh. thus sucks... */
5749       if(size) {
5750         pCodeOp *pctemp;
5751         
5752         pctemp = pic16_popGetTempReg(1);
5753         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5754         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5756         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5758         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759         pic16_popReleaseTempReg(pctemp, 1);
5760       } else {
5761         /* Signed char comparison */
5762         /* Special thanks to Nikolai Golovchenko for this snippet */
5763         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5764         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5765         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5766         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5767         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5768         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5769
5770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5771         genSkipc(&rFalseIfx);
5772           
5773         if(ifx) ifx->generated = 1;
5774
5775             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776               goto check_carry;
5777
5778         return;
5779       }
5780
5781     } else {
5782
5783       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5784       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5785     }
5786
5787
5788     /* The rest of the bytes of a multi-byte compare */
5789     while (size) {
5790
5791       emitSKPZ;
5792       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5793       size--;
5794
5795       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5796       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5797
5798
5799     }
5800
5801     pic16_emitpLabel(lbl->key);
5802
5803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5804     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5805         (AOP_TYPE(result) == AOP_REG)) {
5806       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5807       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5808     } else {
5809       genSkipc(&rFalseIfx);
5810     }         
5811     //genSkipc(&rFalseIfx);
5812     if(ifx) ifx->generated = 1;
5813
5814
5815             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5816               goto check_carry;
5817
5818     return;
5819
5820   }
5821
5822 check_carry:
5823   if ((AOP_TYPE(result) != AOP_CRY) 
5824         && AOP_SIZE(result)) {
5825     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5826
5827     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5828
5829     pic16_outBitC(result);
5830   } else {
5831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832     /* if the result is used in the next
5833        ifx conditional branch then generate
5834        code a little differently */
5835     if (ifx )
5836       genIfxJump (ifx,"c");
5837     else
5838       pic16_outBitC(result);
5839     /* leave the result in acc */
5840   }
5841
5842 }
5843
5844 #else   /* old version of genCmp() */   /* } else { */
5845
5846 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5847 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5848         operand *result, int offset, int invert_op)
5849 {
5850   /* add code here */
5851   
5852   /* check condition, > or < ?? */
5853   if(rIfx->condition != 0)invert_op ^= 1;
5854   
5855   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5856
5857   if(!ifx)invert_op ^= 1;
5858
5859   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5860       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5861   
5862   /* do selection */
5863   if(!invert_op)return POC_CPFSGT;
5864   else return POC_CPFSLT;
5865 }
5866
5867 static int compareAopfirstpass=1;
5868
5869 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5870             operand *oper, int offset, operand *result,
5871             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5872             symbol *tlbl)
5873 {
5874   int op;
5875   symbol *truelbl;
5876
5877   /* invert if there is a result to be loaded, in order to fit,
5878    * SETC/CLRC sequence */
5879   if(AOP_SIZE(result))invert_op ^= 1;
5880
5881 //  if(sign && !offset)invert_op ^= 1;
5882   
5883 //  if(sign)invert_op ^= 1;
5884   
5885   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5886
5887   if(AOP_SIZE(result) && compareAopfirstpass) {
5888     if(!ifx) {
5889       if(pcop2)
5890         pic16_emitpcode(POC_SETF, pcop2);
5891       else
5892         emitSETC;
5893     } else {
5894       if(pcop2)
5895         pic16_emitpcode(POC_CLRF, pcop2);
5896       else
5897         emitCLRC;
5898     }
5899   }
5900
5901   compareAopfirstpass = 0;
5902
5903       /* there is a bug when comparing operands with size > 1,
5904        * because higher bytes can be equal and test should be performed
5905        * to the next lower byte, current algorithm, considers operands
5906        * inequal in these cases! -- VR 20041107 */
5907
5908     
5909   if(pcop)
5910     pic16_emitpcode(op, pcop);
5911   else
5912     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5913
5914
5915   if((!sign || !offset) && AOP_SIZE(result)) {
5916     if(!ifx) {
5917       if(pcop2)
5918         pic16_emitpcode(POC_CLRF, pcop2);
5919         else
5920         emitCLRC;
5921     } else {
5922       if(pcop2)
5923         pic16_emitpcode(POC_SETF, pcop2);
5924       else
5925         emitSETC;
5926     }
5927     
5928     /* don't emit final branch (offset == 0) */
5929     if(offset) {
5930
5931       if(pcop2)
5932         pic16_emitpcode(POC_RRCF, pcop2);
5933
5934       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5935     }
5936   } else {
5937     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5938       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5939             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5940
5941       truelbl = newiTempLabel( NULL );
5942       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5943       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5944         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5945       else
5946         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947       pic16_emitpLabel(truelbl->key);
5948     } else {
5949       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5950     }
5951   }
5952 }
5953
5954
5955   
5956
5957 #if 1   /* { */
5958 static void genCmp (operand *left, operand *right,
5959                     operand *result, iCode *ifx, int sign)
5960 {
5961   int size, cmpop=1;
5962   long lit = 0L;
5963   resolvedIfx rFalseIfx;
5964   symbol *falselbl, *tlbl;
5965
5966     FENTRY;
5967     
5968     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5969
5970     resolveIfx(&rFalseIfx, ifx);
5971     size = max(AOP_SIZE(left), AOP_SIZE(right));
5972     
5973     /* if left & right are bit variables */
5974     if(AOP_TYPE(left) == AOP_CRY
5975       && AOP_TYPE(right) == AOP_CRY ) {
5976
5977         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5978         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5979         
5980         werror(W_POSSBUG2, __FILE__, __LINE__);
5981         exit(-1);
5982     }
5983     
5984     /* if literal is on the right then swap with left */
5985     if((AOP_TYPE(right) == AOP_LIT)) {
5986       operand *tmp = right ;
5987 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5988
5989         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5990
5991 //      lit = (lit - 1) & mask;
5992         right = left;
5993         left = tmp;
5994         rFalseIfx.condition ^= 1;               /* reverse compare */
5995     } else
5996     if ((AOP_TYPE(left) == AOP_LIT)) {
5997       /* float compares are handled by support functions */
5998       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5999     }
6000
6001     /* actual comparing algorithm */
6002 //    size = AOP_SIZE( right );
6003
6004     falselbl = newiTempLabel( NULL );
6005     if(AOP_TYPE(left) == AOP_LIT) {
6006       /* compare to literal */
6007       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6008       
6009       if(sign) {
6010         pCodeOp *pct, *pct2;
6011         symbol *tlbl1;
6012
6013         /* signed compare */
6014         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6015
6016         pct = pic16_popCopyReg(&pic16_pc_prodl);
6017         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6018         tlbl = newiTempLabel( NULL );
6019         
6020         /* first compare signs:
6021          *  a. if both are positive, compare just like unsigned
6022          *  b. if both are negative, invert cmpop, compare just like unsigned
6023          *  c. if different signs, determine the result directly */
6024
6025         size--;
6026
6027 #if 1
6028         /* { */
6029         tlbl1 = newiTempLabel( NULL );
6030 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6031
6032         if(lit > 0) {
6033
6034           /* literal is zero or positive:
6035            *  a. if carry is zero, too, continue compare,
6036            *  b. if carry is set, then continue depending on cmpop ^ condition:
6037            *    1. '<' return false (literal < variable),
6038            *    2. '>' return true (literal > variable) */
6039 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6040           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6041           
6042           
6043           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6044           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6045         } else 
6046         if(lit < 0) {
6047           
6048           /* literal is negative:
6049            *  a. if carry is set, too, continue compare,
6050            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6051            *    1. '<' return true (literal < variable),
6052            *    2. '>' return false (literal > variable) */
6053 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6054           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6055           
6056           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6057           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6058         }
6059 #if 1
6060         else {
6061           /* lit == 0 */
6062           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6063           
6064           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6065           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6066         }
6067 #endif
6068         
6069         
6070         pic16_emitpLabel( tlbl1->key );
6071 #endif  /* } */
6072
6073         compareAopfirstpass=1;
6074 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6075 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6076 //        pic16_emitpcode(POC_MOVWF, pct);
6077
6078 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6079         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6080 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6082
6083         /* generic case */        
6084           while( size-- ) {
6085 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6086 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6087 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6088 //            pic16_emitpcode(POC_MOVWF, pct);
6089
6090 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6091             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6092             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6093 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6094 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6095           }
6096 //        }
6097         
6098         if(ifx)ifx->generated = 1;
6099
6100         if(AOP_SIZE(result)) {
6101           pic16_emitpLabel(tlbl->key);
6102           pic16_emitpLabel(falselbl->key);
6103           pic16_outBitOp( result, pct2 );
6104         } else {
6105           pic16_emitpLabel(tlbl->key);
6106         }
6107       } else {
6108
6109
6110         /* unsigned compare */      
6111         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6112     
6113         compareAopfirstpass=1;
6114         while(size--) {
6115           
6116           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6117           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6118
6119         }
6120
6121         if(ifx)ifx->generated = 1;
6122
6123
6124         if(AOP_SIZE(result)) {
6125           pic16_emitpLabel(falselbl->key);
6126           pic16_outBitC( result );
6127         }
6128
6129       }
6130     } else {
6131       /* compare registers */
6132       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6133
6134
6135       if(sign) {
6136         pCodeOp *pct, *pct2;
6137         
6138         /* signed compare */
6139         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6140
6141         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6142         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6143         tlbl = newiTempLabel( NULL );
6144         
6145         compareAopfirstpass=1;
6146
6147         size--;
6148         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151         pic16_emitpcode(POC_MOVWF, pct);
6152
6153         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6156
6157         /* WREG already holds left + 0x80 */
6158         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159         
6160         while( size-- ) {
6161           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6162 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6163           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6164           pic16_emitpcode(POC_MOVWF, pct);
6165                 
6166           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6168           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6169
6170           /* WREG already holds left + 0x80 */
6171           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6172 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6173         }
6174         
6175         if(ifx)ifx->generated = 1;
6176
6177         if(AOP_SIZE(result)) {
6178           pic16_emitpLabel(tlbl->key);
6179           pic16_emitpLabel(falselbl->key);
6180           pic16_outBitOp( result, pct2 );
6181         } else {
6182           pic16_emitpLabel(tlbl->key);
6183         }
6184
6185       } else {
6186         /* unsigned compare */      
6187         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6188
6189         compareAopfirstpass=1;
6190         while(size--) {
6191           
6192           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6193           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6194
6195         }
6196
6197         if(ifx)ifx->generated = 1;
6198         if(AOP_SIZE(result)) {
6199
6200           pic16_emitpLabel(falselbl->key);
6201           pic16_outBitC( result );
6202         }
6203
6204       }
6205     }
6206 }
6207
6208 #else    /* } else { */
6209
6210 /* new version of genCmp -- VR 20041012 */
6211 static void genCmp (operand *left,operand *right,
6212                     operand *result, iCode *ifx, int sign)
6213 {
6214   int size; //, offset = 0 ;
6215   unsigned long lit = 0L,i = 0;
6216   resolvedIfx rFalseIfx;
6217   int willCheckCarry=0;
6218   //  resolvedIfx rTrueIfx;
6219   symbol *truelbl;
6220
6221     FENTRY;
6222   
6223   /* General concept:
6224    * subtract right from left if at the end the carry flag is set then we
6225    * know that left is greater than right */
6226             
6227   resolveIfx(&rFalseIfx,ifx);
6228   truelbl  = newiTempLabel(NULL);
6229   size = max(AOP_SIZE(left),AOP_SIZE(right));
6230
6231   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6232
6233   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6234    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6235   
6236
6237   /* if literal is on the right then swap with left */
6238   if ((AOP_TYPE(right) == AOP_LIT)) {
6239     operand *tmp = right ;
6240     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6241
6242       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6243
6244 //      lit = (lit - 1) & mask;
6245       right = left;
6246       left = tmp;
6247       rFalseIfx.condition ^= 1;         /* reverse compare */
6248   } else
6249   if ((AOP_TYPE(left) == AOP_LIT)) {
6250     /* float compares are handled by support functions */
6251     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6252   }
6253
6254
6255   //if(IC_TRUE(ifx) == NULL)
6256   /* if left & right are bit variables */
6257   if (AOP_TYPE(left) == AOP_CRY &&
6258       AOP_TYPE(right) == AOP_CRY ) {
6259
6260     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6261     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6262
6263   } else {
6264     symbol *lbl  = newiTempLabel(NULL);
6265
6266     if(AOP_TYPE(left) == AOP_LIT) {
6267       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6268
6269       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6270         willCheckCarry = 1;
6271       else willCheckCarry = 0;
6272
6273       /* Special cases */
6274       if((lit == 0) && (sign == 0)) {
6275         /* unsigned compare to 0 */
6276         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6277         
6278         size--;
6279         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6280         while(size) 
6281           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6282
6283         genSkipz2(&rFalseIfx,0);
6284         if(ifx)ifx->generated = 1;
6285         return;
6286       }
6287
6288       if(size==1) {
6289         /* Special cases */
6290         lit &= 0xff;
6291         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6292           /* degenerate compare can never be true */
6293           if(rFalseIfx.condition == 0)
6294             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6295
6296           if(ifx) ifx->generated = 1;
6297           return;
6298         }
6299
6300         if(sign) {
6301           /* signed comparisons to a literal byte */
6302           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6303
6304           int lp1 = (lit+1) & 0xff;
6305
6306           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6307           switch (lp1) {
6308           case 0:
6309             rFalseIfx.condition ^= 1;
6310             genSkipCond(&rFalseIfx,right,0,7);
6311             break;
6312           case 0x7f:
6313             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6314             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6315             genSkipz2(&rFalseIfx,1);
6316             break;
6317           default:
6318             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6319             
6320             if(rFalseIfx.condition)
6321               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6322             else
6323               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6324
6325             if(willCheckCarry) {
6326               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6327               else { emitSETC; emitCLRC; }
6328               
6329             } else {
6330               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6331             }              
6332                       
6333 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6334             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6335             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6336             rFalseIfx.condition ^= 1;
6337             genSkipc(&rFalseIfx);
6338 */
6339             break;
6340           }
6341         } else {
6342           /* unsigned comparisons to a literal byte */
6343           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6344
6345           switch(lit & 0xff ) {
6346                           /* special cases */
6347           case 0:
6348             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6349             genSkipz2(&rFalseIfx,0);
6350             break;
6351           case 0x7f:
6352             rFalseIfx.condition ^= 1;
6353             genSkipCond(&rFalseIfx,right,0,7);
6354             break;
6355           default:
6356             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6357             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6358             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6359             rFalseIfx.condition ^= 1;
6360             if (AOP_TYPE(result) == AOP_CRY)
6361               genSkipc(&rFalseIfx);
6362             else {
6363               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6364               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6365             }         
6366             break;
6367           }
6368         }
6369
6370         if(ifx) ifx->generated = 1;
6371         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6372                 goto check_carry;
6373         return;
6374
6375       } else {
6376
6377         /* Size is greater than 1 */
6378
6379         if(sign) {
6380           int lp1 = lit+1;
6381
6382           size--;
6383
6384           if(lp1 == 0) {
6385             /* this means lit = 0xffffffff, or -1 */
6386
6387
6388             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6389             rFalseIfx.condition ^= 1;
6390             genSkipCond(&rFalseIfx,right,size,7);
6391             if(ifx) ifx->generated = 1;
6392             return;
6393           }
6394
6395           if(lit == 0) {
6396             int s = size;
6397
6398             if(rFalseIfx.condition) {
6399               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6400               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6401             }
6402
6403             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6404             while(size--)
6405               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6406
6407
6408             emitSKPZ;
6409             if(rFalseIfx.condition) {
6410               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6411               pic16_emitpLabel(truelbl->key);
6412             }else {
6413               rFalseIfx.condition ^= 1;
6414               genSkipCond(&rFalseIfx,right,s,7);
6415             }
6416
6417             if(ifx) ifx->generated = 1;
6418             return;
6419           }
6420
6421           if((size == 1) &&  (0 == (lp1&0xff))) {
6422             /* lower byte of signed word is zero */
6423             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6424             i = ((lp1 >> 8) & 0xff) ^0x80;
6425             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6426             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6427             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6428             rFalseIfx.condition ^= 1;
6429             genSkipc(&rFalseIfx);
6430
6431
6432             if(ifx) ifx->generated = 1;
6433             return;
6434           }
6435
6436           if(lit & (0x80 << (size*8))) {
6437             /* Lit is less than zero */
6438             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6439             //rFalseIfx.condition ^= 1;
6440             //genSkipCond(&rFalseIfx,left,size,7);
6441             //rFalseIfx.condition ^= 1;
6442             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6443             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6444
6445             if(rFalseIfx.condition)
6446               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6447             else
6448               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6449
6450
6451           } else {
6452             /* Lit is greater than or equal to zero */
6453             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6454             //rFalseIfx.condition ^= 1;
6455             //genSkipCond(&rFalseIfx,right,size,7);
6456             //rFalseIfx.condition ^= 1;
6457
6458             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6459             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6460
6461             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6462             if(rFalseIfx.condition)
6463               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6464             else
6465               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6466
6467           }
6468
6469
6470           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6471           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6472
6473           while(size--) {
6474
6475             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6476             emitSKPNZ;
6477             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6478           }
6479           rFalseIfx.condition ^= 1;
6480           //rFalseIfx.condition = 1;
6481           genSkipc(&rFalseIfx);
6482
6483           pic16_emitpLabel(truelbl->key);
6484
6485           if(ifx) ifx->generated = 1;
6486           return;
6487           // end of if (sign)
6488         } else {
6489
6490           /* compare word or long to an unsigned literal on the right.*/
6491
6492
6493           size--;
6494           if(lit < 0xff) {
6495             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6496             switch (lit) {
6497             case 0:
6498               break; /* handled above */
6499 /*
6500             case 0xff:
6501               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6502               while(size--)
6503                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6504               genSkipz2(&rFalseIfx,0);
6505               break;
6506 */
6507             default:
6508               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6509               while(--size)
6510                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6511
6512               emitSKPZ;
6513               if(rFalseIfx.condition)
6514                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6515               else
6516                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6517
6518
6519               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6520               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6521
6522               rFalseIfx.condition ^= 1;
6523               genSkipc(&rFalseIfx);
6524             }
6525
6526             pic16_emitpLabel(truelbl->key);
6527
6528             if(ifx) ifx->generated = 1;
6529             return;
6530           }
6531
6532
6533           lit++;
6534           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6535           i = (lit >> (size*8)) & 0xff;
6536
6537           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6538           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6539
6540           while(size--) {
6541             i = (lit >> (size*8)) & 0xff;
6542
6543             if(i) {
6544               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6545               emitSKPNZ;
6546               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6547             } else {
6548               /* this byte of the lit is zero, 
6549                * if it's not the last then OR in the variable */
6550               if(size)
6551                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6552             }
6553           }
6554
6555
6556           pic16_emitpLabel(lbl->key);
6557
6558           rFalseIfx.condition ^= 1;
6559
6560           genSkipc(&rFalseIfx);
6561         }
6562
6563         if(sign)
6564           pic16_emitpLabel(truelbl->key);
6565         if(ifx) ifx->generated = 1;
6566         return;
6567       }
6568     }
6569     /* Compare two variables */
6570
6571     DEBUGpic16_emitcode(";sign","%d",sign);
6572
6573     size--;
6574     if(sign) {
6575       /* Sigh. thus sucks... */
6576       if(size) {
6577         pCodeOp *pctemp;
6578         
6579         pctemp = pic16_popGetTempReg(1);
6580         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6581         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6582         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6583         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6584         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6585         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586         pic16_popReleaseTempReg(pctemp, 1);
6587       } else {
6588         /* Signed char comparison */
6589         /* Special thanks to Nikolai Golovchenko for this snippet */
6590         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6591         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6592         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6593         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6594         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6595         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6596
6597         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6598         genSkipc(&rFalseIfx);
6599           
6600         if(ifx) ifx->generated = 1;
6601         return;
6602       }
6603
6604     } else {
6605
6606       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6607       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6608     }
6609
6610
6611     /* The rest of the bytes of a multi-byte compare */
6612     while (size) {
6613
6614       emitSKPZ;
6615       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6616       size--;
6617
6618       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6619       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6620
6621
6622     }
6623
6624     pic16_emitpLabel(lbl->key);
6625
6626     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6627     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6628         (AOP_TYPE(result) == AOP_REG)) {
6629       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6630       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6631     } else {
6632       genSkipc(&rFalseIfx);
6633     }         
6634     //genSkipc(&rFalseIfx);
6635     if(ifx) ifx->generated = 1;
6636
6637     return;
6638
6639   }
6640
6641 check_carry:
6642   if ((AOP_TYPE(result) != AOP_CRY) 
6643         && AOP_SIZE(result)) {
6644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6645
6646     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6647
6648     pic16_outBitC(result);
6649   } else {
6650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6651     /* if the result is used in the next
6652        ifx conditional branch then generate
6653        code a little differently */
6654     if (ifx )
6655       genIfxJump (ifx,"c");
6656     else
6657       pic16_outBitC(result);
6658     /* leave the result in acc */
6659   }
6660
6661 }
6662 #endif  /* } */
6663
6664
6665 #endif  /* } */
6666
6667
6668
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpGt :- greater than comparison                             */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpGt (iCode *ic, iCode *ifx)
6673 {
6674   operand *left, *right, *result;
6675   sym_link *letype , *retype;
6676   int sign ;
6677
6678     FENTRY;
6679     
6680     left = IC_LEFT(ic);
6681     right= IC_RIGHT(ic);
6682     result = IC_RESULT(ic);
6683
6684     letype = getSpec(operandType(left));
6685     retype =getSpec(operandType(right));
6686     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6687     /* assign the amsops */
6688     pic16_aopOp (left,ic,FALSE);
6689     pic16_aopOp (right,ic,FALSE);
6690     pic16_aopOp (result,ic,TRUE);
6691
6692     genCmp(right, left, result, ifx, sign);
6693
6694     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6695     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696     pic16_freeAsmop(result,NULL,ic,TRUE); 
6697 }
6698
6699 /*-----------------------------------------------------------------*/
6700 /* genCmpLt - less than comparisons                                */
6701 /*-----------------------------------------------------------------*/
6702 static void genCmpLt (iCode *ic, iCode *ifx)
6703 {
6704   operand *left, *right, *result;
6705   sym_link *letype , *retype;
6706   int sign ;
6707
6708     FENTRY;
6709
6710     left = IC_LEFT(ic);
6711     right= IC_RIGHT(ic);
6712     result = IC_RESULT(ic);
6713
6714     letype = getSpec(operandType(left));
6715     retype =getSpec(operandType(right));
6716     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6717
6718     /* assign the amsops */
6719     pic16_aopOp (left,ic,FALSE);
6720     pic16_aopOp (right,ic,FALSE);
6721     pic16_aopOp (result,ic,TRUE);
6722
6723     genCmp(left, right, result, ifx, sign);
6724
6725     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6726     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727     pic16_freeAsmop(result,NULL,ic,TRUE); 
6728 }
6729
6730 #if 0
6731 // not needed ATM
6732 // FIXME reenable literal optimisation when the pic16 port is stable
6733
6734 /*-----------------------------------------------------------------*/
6735 /* genc16bit2lit - compare a 16 bit value to a literal             */
6736 /*-----------------------------------------------------------------*/
6737 static void genc16bit2lit(operand *op, int lit, int offset)
6738 {
6739   int i;
6740
6741   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6742   if( (lit&0xff) == 0) 
6743     i=1;
6744   else
6745     i=0;
6746
6747   switch( BYTEofLONG(lit,i)) { 
6748   case 0:
6749     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6750     break;
6751   case 1:
6752     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6753     break;
6754   case 0xff:
6755     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6756     break;
6757   default:
6758     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6759     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6760   }
6761
6762   i ^= 1;
6763
6764   switch( BYTEofLONG(lit,i)) { 
6765   case 0:
6766     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6767     break;
6768   case 1:
6769     emitSKPNZ;
6770     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6771     break;
6772   case 0xff:
6773     emitSKPNZ;
6774     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6775     break;
6776   default:
6777     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6778     emitSKPNZ;
6779     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6780
6781   }
6782
6783 }
6784 #endif
6785
6786 #if 0
6787 // not needed ATM
6788 /*-----------------------------------------------------------------*/
6789 /* gencjneshort - compare and jump if not equal                    */
6790 /*-----------------------------------------------------------------*/
6791 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6792 {
6793   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6794   int offset = 0;
6795   int res_offset = 0;  /* the result may be a different size then left or right */
6796   int res_size = AOP_SIZE(result);
6797   resolvedIfx rIfx;
6798   symbol *lbl, *lbl_done;
6799
6800   unsigned long lit = 0L;
6801   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6802
6803   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6805   if(result)
6806     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6807   resolveIfx(&rIfx,ifx);
6808   lbl =  newiTempLabel(NULL);
6809   lbl_done =  newiTempLabel(NULL);
6810
6811
6812   /* if the left side is a literal or 
6813      if the right is in a pointer register and left 
6814      is not */
6815   if ((AOP_TYPE(left) == AOP_LIT) || 
6816       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6817     operand *t = right;
6818     right = left;
6819     left = t;
6820   }
6821   if(AOP_TYPE(right) == AOP_LIT)
6822     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6823
6824   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6825     preserve_result = 1;
6826
6827   if(result && !preserve_result)
6828     {
6829       int i;
6830       for(i = 0; i < AOP_SIZE(result); i++)
6831         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6832     }
6833
6834
6835   /* if the right side is a literal then anything goes */
6836   if (AOP_TYPE(right) == AOP_LIT &&
6837       AOP_TYPE(left) != AOP_DIR ) {
6838     switch(size) {
6839     case 2:
6840       genc16bit2lit(left, lit, 0);
6841       emitSKPZ;
6842       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6843       break;
6844     default:
6845       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846       while (size--) {
6847         if(lit & 0xff) {
6848           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6849           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6850         } else {
6851           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6852         }
6853
6854         emitSKPZ;
6855         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6856         offset++;
6857         if(res_offset < res_size-1)
6858           res_offset++;
6859         lit >>= 8;
6860       }
6861       break;
6862     }
6863   }
6864
6865   /* if the right side is in a register or in direct space or
6866      if the left is a pointer register & right is not */    
6867   else if (AOP_TYPE(right) == AOP_REG ||
6868            AOP_TYPE(right) == AOP_DIR || 
6869            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6870            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6871     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6872     int lbl_key = lbl->key;
6873
6874     if(result) {
6875       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6876       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6877     }else {
6878       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6879       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6880               __FUNCTION__,__LINE__);
6881       return;
6882     }
6883    
6884 /*     switch(size) { */
6885 /*     case 2: */
6886 /*       genc16bit2lit(left, lit, 0); */
6887 /*       emitSKPNZ; */
6888 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6889 /*       break; */
6890 /*     default: */
6891     while (size--) {
6892       int emit_skip=1;
6893       if((AOP_TYPE(left) == AOP_DIR) && 
6894          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6895
6896         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6897         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6898
6899       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6900             
6901         switch (lit & 0xff) {
6902         case 0:
6903           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6904           break;
6905         case 1:
6906           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6907           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6908           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6909           emit_skip=0;
6910           break;
6911         case 0xff:
6912           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6913           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6914           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6915           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6916           emit_skip=0;
6917           break;
6918         default:
6919           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6921         }
6922         lit >>= 8;
6923
6924       } else {
6925         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6926       }
6927       if(emit_skip) {
6928         if(AOP_TYPE(result) == AOP_CRY) {
6929           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6930           if(rIfx.condition)
6931             emitSKPNZ;
6932           else
6933             emitSKPZ;
6934           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6935         } else {
6936           /* fix me. probably need to check result size too */
6937           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6938           if(rIfx.condition)
6939             emitSKPZ;
6940           else
6941             emitSKPNZ;
6942           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6943           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6944         }
6945         if(ifx)
6946           ifx->generated=1;
6947       }
6948       emit_skip++;
6949       offset++;
6950       if(res_offset < res_size-1)
6951         res_offset++;
6952     }
6953 /*       break; */
6954 /*     } */
6955   } else if(AOP_TYPE(right) == AOP_REG &&
6956             AOP_TYPE(left) != AOP_DIR){
6957
6958     while(size--) {
6959       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6961       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6962       if(rIfx.condition)
6963         emitSKPNZ;
6964       else
6965         emitSKPZ;
6966       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6967       offset++;
6968       if(res_offset < res_size-1)
6969         res_offset++;
6970     }
6971       
6972   }else{
6973     /* right is a pointer reg need both a & b */
6974     while(size--) {
6975       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6976       if(strcmp(l,"b"))
6977         pic16_emitcode("mov","b,%s",l);
6978       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6979       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6980       offset++;
6981     }
6982   }
6983
6984   if(result && preserve_result)
6985     {
6986       int i;
6987       for(i = 0; i < AOP_SIZE(result); i++)
6988         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6989     }
6990
6991   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6992
6993   if(result && preserve_result)
6994     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6995
6996   if(!rIfx.condition)
6997     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6998
6999   pic16_emitpLabel(lbl->key);
7000
7001   if(result && preserve_result)
7002     {
7003       int i;
7004       for(i = 0; i < AOP_SIZE(result); i++)
7005         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7006
7007       pic16_emitpLabel(lbl_done->key);
7008    }
7009
7010   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7011
7012   if(ifx)
7013     ifx->generated = 1;
7014 }
7015 #endif
7016
7017 #if 0
7018 /*-----------------------------------------------------------------*/
7019 /* gencjne - compare and jump if not equal                         */
7020 /*-----------------------------------------------------------------*/
7021 static void gencjne(operand *left, operand *right, iCode *ifx)
7022 {
7023     symbol *tlbl  = newiTempLabel(NULL);
7024
7025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7026     gencjneshort(left, right, lbl);
7027
7028     pic16_emitcode("mov","a,%s",one);
7029     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7030     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7031     pic16_emitcode("clr","a");
7032     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7033
7034     pic16_emitpLabel(lbl->key);
7035     pic16_emitpLabel(tlbl->key);
7036
7037 }
7038 #endif
7039
7040
7041 /*-----------------------------------------------------------------*/
7042 /* is_LitOp - check if operand has to be treated as literal        */
7043 /*-----------------------------------------------------------------*/
7044 static bool is_LitOp(operand *op)
7045 {
7046   return ((AOP_TYPE(op) == AOP_LIT)
7047       || ( (AOP_TYPE(op) == AOP_PCODE)
7048           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7049               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7050 }
7051
7052 /*-----------------------------------------------------------------*/
7053 /* is_LitAOp - check if operand has to be treated as literal        */
7054 /*-----------------------------------------------------------------*/
7055 static bool is_LitAOp(asmop *aop)
7056 {
7057   return ((aop->type == AOP_LIT)
7058       || ( (aop->type == AOP_PCODE)
7059           && ( (aop->aopu.pcop->type == PO_LITERAL)
7060               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7061 }
7062
7063
7064
7065 /*-----------------------------------------------------------------*/
7066 /* genCmpEq - generates code for equal to                          */
7067 /*-----------------------------------------------------------------*/
7068 static void genCmpEq (iCode *ic, iCode *ifx)
7069 {
7070   operand *left, *right, *result;
7071   symbol *falselbl = newiTempLabel(NULL);
7072   symbol *donelbl = newiTempLabel(NULL);
7073
7074   int preserve_result = 0;
7075   int generate_result = 0;
7076   int i=0;
7077   unsigned long lit = -1;
7078
7079   FENTRY;
7080   
7081   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7082   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7083   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7084  
7085   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7086
7087   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7088     {
7089       werror(W_POSSBUG2, __FILE__, __LINE__);
7090       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7091       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7092       goto release;
7093     }
7094
7095   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7096     {
7097       operand *tmp = right ;
7098       right = left;
7099       left = tmp;
7100     }
7101
7102   if (AOP_TYPE(right) == AOP_LIT) {
7103     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7104   }
7105
7106   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7107     preserve_result = 1;
7108
7109   if(result && AOP_SIZE(result))
7110     generate_result = 1;
7111
7112   if(generate_result && !preserve_result)
7113     {
7114       for(i = 0; i < AOP_SIZE(result); i++)
7115         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7116     }
7117
7118   for(i=0; i < AOP_SIZE(left); i++)
7119     {
7120       if(AOP_TYPE(left) != AOP_ACC)
7121         {
7122           if(is_LitOp(left))
7123             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7124           else
7125             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7126         }
7127       if(is_LitOp(right)) {
7128         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7129           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7130         }
7131       } else
7132         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7133
7134       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7135     }
7136
7137   // result == true
7138
7139   if(generate_result && preserve_result)
7140     {
7141       for(i = 0; i < AOP_SIZE(result); i++)
7142         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7143     }
7144
7145   if(generate_result)
7146     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7147
7148   if(generate_result && preserve_result)
7149     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7150
7151   if(ifx && IC_TRUE(ifx))
7152     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7153
7154   if(ifx && IC_FALSE(ifx))
7155     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7156
7157   pic16_emitpLabel(falselbl->key);
7158
7159   // result == false
7160
7161   if(ifx && IC_FALSE(ifx))
7162     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7163
7164   if(generate_result && preserve_result)
7165     {
7166       for(i = 0; i < AOP_SIZE(result); i++)
7167         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7168     }
7169
7170   pic16_emitpLabel(donelbl->key);
7171
7172   if(ifx)
7173     ifx->generated = 1;
7174
7175 release:
7176   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7177   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7178   pic16_freeAsmop(result,NULL,ic,TRUE);
7179
7180 }
7181
7182
7183 #if 0
7184 // old version kept for reference
7185
7186 /*-----------------------------------------------------------------*/
7187 /* genCmpEq - generates code for equal to                          */
7188 /*-----------------------------------------------------------------*/
7189 static void genCmpEq (iCode *ic, iCode *ifx)
7190 {
7191     operand *left, *right, *result;
7192     unsigned long lit = 0L;
7193     int size,offset=0;
7194     symbol *falselbl  = newiTempLabel(NULL);
7195
7196
7197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7198
7199     if(ifx)
7200       DEBUGpic16_emitcode ("; ifx is non-null","");
7201     else
7202       DEBUGpic16_emitcode ("; ifx is null","");
7203
7204     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7207
7208     size = max(AOP_SIZE(left),AOP_SIZE(right));
7209
7210     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7211
7212     /* if literal, literal on the right or 
7213     if the right is in a pointer register and left 
7214     is not */
7215     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7216         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7217       operand *tmp = right ;
7218       right = left;
7219       left = tmp;
7220     }
7221
7222
7223     if(ifx && !AOP_SIZE(result)){
7224         symbol *tlbl;
7225         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7226         /* if they are both bit variables */
7227         if (AOP_TYPE(left) == AOP_CRY &&
7228             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7229                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7230             if(AOP_TYPE(right) == AOP_LIT){
7231                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7232                 if(lit == 0L){
7233                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7234                     pic16_emitcode("cpl","c");
7235                 } else if(lit == 1L) {
7236                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7237                 } else {
7238                     pic16_emitcode("clr","c");
7239                 }
7240                 /* AOP_TYPE(right) == AOP_CRY */
7241             } else {
7242                 symbol *lbl = newiTempLabel(NULL);
7243                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7244                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7245                 pic16_emitcode("cpl","c");
7246                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7247             }
7248             /* if true label then we jump if condition
7249             supplied is true */
7250             tlbl = newiTempLabel(NULL);
7251             if ( IC_TRUE(ifx) ) {
7252                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7253                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7254             } else {
7255                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7256                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7257             }
7258             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7259
7260                 {
7261                 /* left and right are both bit variables, result is carry */
7262                         resolvedIfx rIfx;
7263               
7264                         resolveIfx(&rIfx,ifx);
7265
7266                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7267                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7268                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7269                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7270                         genSkipz2(&rIfx,0);
7271                 }
7272         } else {
7273
7274                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7275
7276                         /* They're not both bit variables. Is the right a literal? */
7277                         if(AOP_TYPE(right) == AOP_LIT) {
7278                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7279             
7280                         switch(size) {
7281
7282                                 case 1:
7283                                         switch(lit & 0xff) {
7284                                                 case 1:
7285                                                                 if ( IC_TRUE(ifx) ) {
7286                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7287                                                                         emitSKPNZ;
7288                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7289                                                                 } else {
7290                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7291                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7292                                                                 }
7293                                                                 break;
7294                                                 case 0xff:
7295                                                                 if ( IC_TRUE(ifx) ) {
7296                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7297                                                                         emitSKPNZ;
7298                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7299                                                                 } else {
7300                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7301                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7302                                                                 }
7303                                                                 break;
7304                                                 default:
7305                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7306                                                                 if(lit)
7307                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7308                                                                 genSkip(ifx,'z');
7309                                         } // switch lit
7310
7311
7312                                         /* end of size == 1 */
7313                                         break;
7314               
7315                                 case 2:
7316                                         genc16bit2lit(left,lit,offset);
7317                                         genSkip(ifx,'z');
7318                                         break;
7319                                         /* end of size == 2 */
7320
7321                                 default:
7322                                         /* size is 4 */
7323                                         if(lit==0) {
7324                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7325                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7326                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7327                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7328                                                 genSkip(ifx,'z');
7329                                         } else {
7330                                                 /* search for patterns that can be optimized */
7331
7332                                                 genc16bit2lit(left,lit,0);
7333                                                 lit >>= 16;
7334                                                 if(lit) {
7335                                                                 if(IC_TRUE(ifx))
7336                                                                 emitSKPZ; // if hi word unequal
7337                                                                 else
7338                                                                 emitSKPNZ; // if hi word equal
7339                                                                 // fail early
7340                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7341                                                         genc16bit2lit(left,lit,2);
7342                                                         genSkip(ifx,'z');
7343                                                 } else {
7344                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7345                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7346                                                         genSkip(ifx,'z');
7347                                                 }
7348                                         }
7349                                                 pic16_emitpLabel(falselbl->key);
7350                                                 break;
7351
7352                         } // switch size
7353           
7354                         ifx->generated = 1;
7355                         goto release ;
7356             
7357
7358           } else if(AOP_TYPE(right) == AOP_CRY ) {
7359             /* we know the left is not a bit, but that the right is */
7360             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7361             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7362                       pic16_popGet(AOP(right),offset));
7363             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7364
7365             /* if the two are equal, then W will be 0 and the Z bit is set
7366              * we could test Z now, or go ahead and check the high order bytes if
7367              * the variable we're comparing is larger than a byte. */
7368
7369             while(--size)
7370               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7371
7372             if ( IC_TRUE(ifx) ) {
7373               emitSKPNZ;
7374               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7375               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7376             } else {
7377               emitSKPZ;
7378               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7379               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7380             }
7381
7382           } else {
7383             /* They're both variables that are larger than bits */
7384             int s = size;
7385
7386             tlbl = newiTempLabel(NULL);
7387
7388             while(size--) {
7389               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7390               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7391
7392               if ( IC_TRUE(ifx) ) {
7393                 if(size) {
7394                   emitSKPZ;
7395                 
7396                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7397
7398                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7399                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7400                 } else {
7401                   emitSKPNZ;
7402
7403                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7404
7405
7406                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7407                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7408                 }
7409               } else {
7410                 emitSKPZ;
7411
7412                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7413
7414                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7415                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7416               }
7417               offset++;
7418             }
7419             if(s>1 && IC_TRUE(ifx)) {
7420               pic16_emitpLabel(tlbl->key);
7421               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7422             }
7423           }
7424         }
7425         /* mark the icode as generated */
7426         ifx->generated = 1;
7427         goto release ;
7428     }
7429
7430     /* if they are both bit variables */
7431     if (AOP_TYPE(left) == AOP_CRY &&
7432         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7433         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7434         if(AOP_TYPE(right) == AOP_LIT){
7435             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7436             if(lit == 0L){
7437                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7438                 pic16_emitcode("cpl","c");
7439             } else if(lit == 1L) {
7440                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7441             } else {
7442                 pic16_emitcode("clr","c");
7443             }
7444             /* AOP_TYPE(right) == AOP_CRY */
7445         } else {
7446             symbol *lbl = newiTempLabel(NULL);
7447             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7448             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7449             pic16_emitcode("cpl","c");
7450             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7451         }
7452         /* c = 1 if egal */
7453         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7454             pic16_outBitC(result);
7455             goto release ;
7456         }
7457         if (ifx) {
7458             genIfxJump (ifx,"c");
7459             goto release ;
7460         }
7461         /* if the result is used in an arithmetic operation
7462         then put the result in place */
7463         pic16_outBitC(result);
7464     } else {
7465       
7466       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7467       gencjne(left,right,result,ifx);
7468 /*
7469       if(ifx) 
7470         gencjne(left,right,newiTempLabel(NULL));
7471       else {
7472         if(IC_TRUE(ifx)->key)
7473           gencjne(left,right,IC_TRUE(ifx)->key);
7474         else
7475           gencjne(left,right,IC_FALSE(ifx)->key);
7476         ifx->generated = 1;
7477         goto release ;
7478       }
7479       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7480         pic16_aopPut(AOP(result),"a",0);
7481         goto release ;
7482       }
7483
7484       if (ifx) {
7485         genIfxJump (ifx,"a");
7486         goto release ;
7487       }
7488 */
7489       /* if the result is used in an arithmetic operation
7490          then put the result in place */
7491 /*
7492       if (AOP_TYPE(result) != AOP_CRY) 
7493         pic16_outAcc(result);
7494 */
7495       /* leave the result in acc */
7496     }
7497
7498 release:
7499     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7500     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7501     pic16_freeAsmop(result,NULL,ic,TRUE);
7502 }
7503 #endif
7504
7505 /*-----------------------------------------------------------------*/
7506 /* ifxForOp - returns the icode containing the ifx for operand     */
7507 /*-----------------------------------------------------------------*/
7508 static iCode *ifxForOp ( operand *op, iCode *ic )
7509 {
7510   FENTRY2;
7511
7512     /* if true symbol then needs to be assigned */
7513     if (IS_TRUE_SYMOP(op))
7514         return NULL ;
7515
7516     /* if this has register type condition and
7517     the next instruction is ifx with the same operand
7518     and live to of the operand is upto the ifx only then */
7519     if (ic->next
7520         && ic->next->op == IFX
7521         && IC_COND(ic->next)->key == op->key
7522         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7523         ) {
7524                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7525           return ic->next;
7526     }
7527
7528     /*
7529     if (ic->next &&
7530         ic->next->op == IFX &&
7531         IC_COND(ic->next)->key == op->key) {
7532       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7533       return ic->next;
7534     }
7535     */
7536
7537     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7538     if (ic->next &&
7539         ic->next->op == IFX)
7540       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7541
7542     if (ic->next &&
7543         ic->next->op == IFX &&
7544         IC_COND(ic->next)->key == op->key) {
7545       DEBUGpic16_emitcode ("; "," key is okay");
7546       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7547                            OP_SYMBOL(op)->liveTo,
7548                            ic->next->seq);
7549     }
7550
7551 #if 0
7552     /* the code below is completely untested
7553      * it just allows ulong2fs.c compile -- VR */
7554          
7555     ic = ic->next;
7556     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7557                                         __FILE__, __FUNCTION__, __LINE__);
7558         
7559     /* if this has register type condition and
7560     the next instruction is ifx with the same operand
7561     and live to of the operand is upto the ifx only then */
7562     if (ic->next &&
7563         ic->next->op == IFX &&
7564         IC_COND(ic->next)->key == op->key &&
7565         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7566         return ic->next;
7567
7568     if (ic->next &&
7569         ic->next->op == IFX &&
7570         IC_COND(ic->next)->key == op->key) {
7571       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7572       return ic->next;
7573     }
7574
7575     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7576                                         __FILE__, __FUNCTION__, __LINE__);
7577
7578 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7579 #endif
7580
7581     return NULL;
7582 }
7583 /*-----------------------------------------------------------------*/
7584 /* genAndOp - for && operation                                     */
7585 /*-----------------------------------------------------------------*/
7586 static void genAndOp (iCode *ic)
7587 {
7588   operand *left,*right, *result;
7589 /*     symbol *tlbl; */
7590
7591     FENTRY;
7592
7593     /* note here that && operations that are in an
7594     if statement are taken away by backPatchLabels
7595     only those used in arthmetic operations remain */
7596     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7597     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7598     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7599
7600     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7601
7602     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7603     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7604     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7605
7606     /* if both are bit variables */
7607 /*     if (AOP_TYPE(left) == AOP_CRY && */
7608 /*         AOP_TYPE(right) == AOP_CRY ) { */
7609 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7610 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7611 /*         pic16_outBitC(result); */
7612 /*     } else { */
7613 /*         tlbl = newiTempLabel(NULL); */
7614 /*         pic16_toBoolean(left);     */
7615 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7616 /*         pic16_toBoolean(right); */
7617 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7618 /*         pic16_outBitAcc(result); */
7619 /*     } */
7620
7621     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7622     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7623     pic16_freeAsmop(result,NULL,ic,TRUE);
7624 }
7625
7626
7627 /*-----------------------------------------------------------------*/
7628 /* genOrOp - for || operation                                      */
7629 /*-----------------------------------------------------------------*/
7630 /*
7631   tsd pic port -
7632   modified this code, but it doesn't appear to ever get called
7633 */
7634
7635 static void genOrOp (iCode *ic)
7636 {
7637   operand *left,*right, *result;
7638   symbol *tlbl;
7639
7640     FENTRY;  
7641
7642   /* note here that || operations that are in an
7643     if statement are taken away by backPatchLabels
7644     only those used in arthmetic operations remain */
7645     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7646     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7647     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7648
7649     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7650
7651     /* if both are bit variables */
7652     if (AOP_TYPE(left) == AOP_CRY &&
7653         AOP_TYPE(right) == AOP_CRY ) {
7654       pic16_emitcode("clrc","");
7655       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7656                AOP(left)->aopu.aop_dir,
7657                AOP(left)->aopu.aop_dir);
7658       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7659                AOP(right)->aopu.aop_dir,
7660                AOP(right)->aopu.aop_dir);
7661       pic16_emitcode("setc","");
7662
7663     } else {
7664         tlbl = newiTempLabel(NULL);
7665         pic16_toBoolean(left);
7666         emitSKPZ;
7667         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7668         pic16_toBoolean(right);
7669         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7670
7671         pic16_outBitAcc(result);
7672     }
7673
7674     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676     pic16_freeAsmop(result,NULL,ic,TRUE);            
7677 }
7678
7679 /*-----------------------------------------------------------------*/
7680 /* isLiteralBit - test if lit == 2^n                               */
7681 /*-----------------------------------------------------------------*/
7682 static int isLiteralBit(unsigned long lit)
7683 {
7684     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7685     0x100L,0x200L,0x400L,0x800L,
7686     0x1000L,0x2000L,0x4000L,0x8000L,
7687     0x10000L,0x20000L,0x40000L,0x80000L,
7688     0x100000L,0x200000L,0x400000L,0x800000L,
7689     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7690     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7691     int idx;
7692     
7693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7694     for(idx = 0; idx < 32; idx++)
7695         if(lit == pw[idx])
7696             return idx+1;
7697     return 0;
7698 }
7699
7700 /*-----------------------------------------------------------------*/
7701 /* continueIfTrue -                                                */
7702 /*-----------------------------------------------------------------*/
7703 static void continueIfTrue (iCode *ic)
7704 {
7705   FENTRY;
7706   if(IC_TRUE(ic))
7707     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7708   ic->generated = 1;
7709 }
7710
7711 /*-----------------------------------------------------------------*/
7712 /* jmpIfTrue -                                                     */
7713 /*-----------------------------------------------------------------*/
7714 static void jumpIfTrue (iCode *ic)
7715 {
7716   FENTRY;
7717   if(!IC_TRUE(ic))
7718     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7719   ic->generated = 1;
7720 }
7721
7722 /*-----------------------------------------------------------------*/
7723 /* jmpTrueOrFalse -                                                */
7724 /*-----------------------------------------------------------------*/
7725 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7726 {
7727   // ugly but optimized by peephole
7728   FENTRY;
7729   if(IC_TRUE(ic)){
7730     symbol *nlbl = newiTempLabel(NULL);
7731       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7732       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7733       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7734       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7735   } else {
7736     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7737     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7738   }
7739   ic->generated = 1;
7740 }
7741
7742 /*-----------------------------------------------------------------*/
7743 /* genAnd  - code for and                                          */
7744 /*-----------------------------------------------------------------*/
7745 static void genAnd (iCode *ic, iCode *ifx)
7746 {
7747   operand *left, *right, *result;
7748   int size, offset=0;  
7749   unsigned long lit = 0L;
7750   int bytelit = 0;
7751   resolvedIfx rIfx;
7752
7753     FENTRY;
7754     
7755   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7756   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7757   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7758
7759   resolveIfx(&rIfx,ifx);
7760
7761   /* if left is a literal & right is not then exchange them */
7762   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7763       AOP_NEEDSACC(left)) {
7764     operand *tmp = right ;
7765     right = left;
7766     left = tmp;
7767   }
7768
7769   /* if result = right then exchange them */
7770   if(pic16_sameRegs(AOP(result),AOP(right))){
7771     operand *tmp = right ;
7772     right = left;
7773     left = tmp;
7774   }
7775
7776   /* if right is bit then exchange them */
7777   if (AOP_TYPE(right) == AOP_CRY &&
7778       AOP_TYPE(left) != AOP_CRY){
7779     operand *tmp = right ;
7780     right = left;
7781     left = tmp;
7782   }
7783   if(AOP_TYPE(right) == AOP_LIT)
7784     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7785
7786   size = AOP_SIZE(result);
7787
7788   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7789
7790   // if(bit & yy)
7791   // result = bit & yy;
7792   if (AOP_TYPE(left) == AOP_CRY){
7793     // c = bit & literal;
7794     if(AOP_TYPE(right) == AOP_LIT){
7795       if(lit & 1) {
7796         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7797           // no change
7798           goto release;
7799         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7800       } else {
7801         // bit(result) = 0;
7802         if(size && (AOP_TYPE(result) == AOP_CRY)){
7803           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7804           goto release;
7805         }
7806         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7807           jumpIfTrue(ifx);
7808           goto release;
7809         }
7810         pic16_emitcode("clr","c");
7811       }
7812     } else {
7813       if (AOP_TYPE(right) == AOP_CRY){
7814         // c = bit & bit;
7815         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7816         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7817       } else {
7818         // c = bit & val;
7819         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7820         // c = lsb
7821         pic16_emitcode("rrc","a");
7822         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7823       }
7824     }
7825     // bit = c
7826     // val = c
7827     if(size)
7828       pic16_outBitC(result);
7829     // if(bit & ...)
7830     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7831       genIfxJump(ifx, "c");           
7832     goto release ;
7833   }
7834
7835   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7836   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7837   if((AOP_TYPE(right) == AOP_LIT) &&
7838      (AOP_TYPE(result) == AOP_CRY) &&
7839      (AOP_TYPE(left) != AOP_CRY)){
7840     int posbit = isLiteralBit(lit);
7841     /* left &  2^n */
7842     if(posbit){
7843       posbit--;
7844       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7845       // bit = left & 2^n
7846       if(size)
7847         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7848       // if(left &  2^n)
7849       else{
7850         if(ifx){
7851 /*
7852           if(IC_TRUE(ifx)) {
7853             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7854             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7855           } else {
7856             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7857             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7858           }
7859 */
7860         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7861         size = AOP_SIZE(left);
7862
7863         {
7864           int bp = posbit, ofs=0;
7865           
7866             while(bp > 7) {
7867               bp -= 8;
7868               ofs++;
7869             }
7870         
7871           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7872                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7873
7874         }
7875 /*
7876           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7877                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7878 */
7879           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7880           
7881           ifx->generated = 1;
7882         }
7883         goto release;
7884       }
7885     } else {
7886       symbol *tlbl = newiTempLabel(NULL);
7887       int sizel = AOP_SIZE(left);
7888
7889       if(size)
7890         emitSETC;
7891
7892       while(sizel--) {
7893         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7894
7895           /* patch provided by Aaron Colwell */
7896           if((posbit = isLiteralBit(bytelit)) != 0) {
7897               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7898                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7899                                                 (posbit-1),0, PO_GPR_REGISTER));
7900
7901               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7902 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7903           } else {
7904               if (bytelit == 0xff) {
7905                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7906                    * a peephole could optimize it out -- VR */
7907                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7908               } else {
7909                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7910                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7911               }
7912
7913               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7914                             pic16_popGetLabel(tlbl->key));
7915           }
7916         
7917 #if 0
7918           /* old code, left here for reference -- VR 09/2004 */
7919           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920           // byte ==  2^n ?
7921           if((posbit = isLiteralBit(bytelit)) != 0)
7922             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7923           else{
7924             if(bytelit != 0x0FFL)
7925               pic16_emitcode("anl","a,%s",
7926                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7927             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7928           }
7929 #endif
7930         }
7931         offset++;
7932       }
7933       // bit = left & literal
7934       if(size) {
7935         emitCLRC;
7936         pic16_emitpLabel(tlbl->key);
7937       }
7938       // if(left & literal)
7939       else {
7940         if(ifx) {
7941           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7942           ifx->generated = 1;
7943         }
7944         pic16_emitpLabel(tlbl->key);
7945         goto release;
7946       }
7947     }
7948
7949     pic16_outBitC(result);
7950     goto release ;
7951   }
7952
7953   /* if left is same as result */
7954   if(pic16_sameRegs(AOP(result),AOP(left))){
7955     int know_W = -1;
7956     for(;size--; offset++,lit>>=8) {
7957       if(AOP_TYPE(right) == AOP_LIT){
7958         switch(lit & 0xff) {
7959         case 0x00:
7960           /*  and'ing with 0 has clears the result */
7961 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7962           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7963           break;
7964         case 0xff:
7965           /* and'ing with 0xff is a nop when the result and left are the same */
7966           break;
7967
7968         default:
7969           {
7970             int p = pic16_my_powof2( (~lit) & 0xff );
7971             if(p>=0) {
7972               /* only one bit is set in the literal, so use a bcf instruction */
7973 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7974               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7975
7976             } else {
7977               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7978               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7979               if(know_W != (lit&0xff))
7980                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7981               know_W = lit &0xff;
7982               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7983             }
7984           }    
7985         }
7986       } else {
7987         if (AOP_TYPE(left) == AOP_ACC) {
7988           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7989         } else {                    
7990           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7991           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7992
7993         }
7994       }
7995     }
7996
7997   } else {
7998     // left & result in different registers
7999     if(AOP_TYPE(result) == AOP_CRY){
8000       // result = bit
8001       // if(size), result in bit
8002       // if(!size && ifx), conditional oper: if(left & right)
8003       symbol *tlbl = newiTempLabel(NULL);
8004       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8005       if(size)
8006         pic16_emitcode("setb","c");
8007       while(sizer--){
8008         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8009         pic16_emitcode("anl","a,%s",
8010                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8012         offset++;
8013       }
8014       if(size){
8015         CLRC;
8016         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8017         pic16_outBitC(result);
8018       } else if(ifx)
8019         jmpTrueOrFalse(ifx, tlbl);
8020     } else {
8021       for(;(size--);offset++) {
8022         // normal case
8023         // result = left & right
8024         if(AOP_TYPE(right) == AOP_LIT){
8025           int t = (lit >> (offset*8)) & 0x0FFL;
8026           switch(t) { 
8027           case 0x00:
8028             pic16_emitcode("clrf","%s",
8029                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8030             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8031             break;
8032           case 0xff:
8033             pic16_emitcode("movf","%s,w",
8034                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8035             pic16_emitcode("movwf","%s",
8036                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8037             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8038             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8039             break;
8040           default:
8041             pic16_emitcode("movlw","0x%x",t);
8042             pic16_emitcode("andwf","%s,w",
8043                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8044             pic16_emitcode("movwf","%s",
8045                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8046               
8047             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8048             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8049             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8050           }
8051           continue;
8052         }
8053
8054         if (AOP_TYPE(left) == AOP_ACC) {
8055           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8056           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8057         } else {
8058           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059           pic16_emitcode("andwf","%s,w",
8060                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8061           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8062           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8063         }
8064         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8065         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8066       }
8067     }
8068   }
8069
8070   release :
8071     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8072   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8073   pic16_freeAsmop(result,NULL,ic,TRUE);     
8074 }
8075
8076 /*-----------------------------------------------------------------*/
8077 /* genOr  - code for or                                            */
8078 /*-----------------------------------------------------------------*/
8079 static void genOr (iCode *ic, iCode *ifx)
8080 {
8081     operand *left, *right, *result;
8082     int size, offset=0;
8083     unsigned long lit = 0L;
8084
8085     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8086
8087     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8088     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8089     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8090
8091     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8092
8093     /* if left is a literal & right is not then exchange them */
8094     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8095         AOP_NEEDSACC(left)) {
8096         operand *tmp = right ;
8097         right = left;
8098         left = tmp;
8099     }
8100
8101     /* if result = right then exchange them */
8102     if(pic16_sameRegs(AOP(result),AOP(right))){
8103         operand *tmp = right ;
8104         right = left;
8105         left = tmp;
8106     }
8107
8108     /* if right is bit then exchange them */
8109     if (AOP_TYPE(right) == AOP_CRY &&
8110         AOP_TYPE(left) != AOP_CRY){
8111         operand *tmp = right ;
8112         right = left;
8113         left = tmp;
8114     }
8115
8116     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8117
8118     if(AOP_TYPE(right) == AOP_LIT)
8119         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8120
8121     size = AOP_SIZE(result);
8122
8123     // if(bit | yy)
8124     // xx = bit | yy;
8125     if (AOP_TYPE(left) == AOP_CRY){
8126         if(AOP_TYPE(right) == AOP_LIT){
8127             // c = bit & literal;
8128             if(lit){
8129                 // lit != 0 => result = 1
8130                 if(AOP_TYPE(result) == AOP_CRY){
8131                   if(size)
8132                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8133                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8134                   //     AOP(result)->aopu.aop_dir,
8135                   //     AOP(result)->aopu.aop_dir);
8136                     else if(ifx)
8137                         continueIfTrue(ifx);
8138                     goto release;
8139                 }
8140             } else {
8141                 // lit == 0 => result = left
8142                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8143                     goto release;
8144                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8145             }
8146         } else {
8147             if (AOP_TYPE(right) == AOP_CRY){
8148               if(pic16_sameRegs(AOP(result),AOP(left))){
8149                 // c = bit | bit;
8150                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8151                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8152                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8153
8154                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8155                          AOP(result)->aopu.aop_dir,
8156                          AOP(result)->aopu.aop_dir);
8157                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8158                          AOP(right)->aopu.aop_dir,
8159                          AOP(right)->aopu.aop_dir);
8160                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8161                          AOP(result)->aopu.aop_dir,
8162                          AOP(result)->aopu.aop_dir);
8163               } else {
8164                 if( AOP_TYPE(result) == AOP_ACC) {
8165                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8166                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8167                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8168                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8169
8170                 } else {
8171
8172                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8173                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8174                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8175                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8176
8177                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8178                                  AOP(result)->aopu.aop_dir,
8179                                  AOP(result)->aopu.aop_dir);
8180                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8181                                  AOP(right)->aopu.aop_dir,
8182                                  AOP(right)->aopu.aop_dir);
8183                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8184                                  AOP(left)->aopu.aop_dir,
8185                                  AOP(left)->aopu.aop_dir);
8186                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8187                                  AOP(result)->aopu.aop_dir,
8188                                  AOP(result)->aopu.aop_dir);
8189                 }
8190               }
8191             } else {
8192                 // c = bit | val;
8193                 symbol *tlbl = newiTempLabel(NULL);
8194                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8195
8196
8197                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8198                 if( AOP_TYPE(right) == AOP_ACC) {
8199                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8200                   emitSKPNZ;
8201                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8202                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8203                 }
8204
8205
8206
8207                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8208                     pic16_emitcode(";XXX setb","c");
8209                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8210                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8211                 pic16_toBoolean(right);
8212                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8213                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8214                     jmpTrueOrFalse(ifx, tlbl);
8215                     goto release;
8216                 } else {
8217                     CLRC;
8218                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8219                 }
8220             }
8221         }
8222         // bit = c
8223         // val = c
8224         if(size)
8225             pic16_outBitC(result);
8226         // if(bit | ...)
8227         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8228             genIfxJump(ifx, "c");           
8229         goto release ;
8230     }
8231
8232     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8233     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8234     if((AOP_TYPE(right) == AOP_LIT) &&
8235        (AOP_TYPE(result) == AOP_CRY) &&
8236        (AOP_TYPE(left) != AOP_CRY)){
8237         if(lit){
8238           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8239             // result = 1
8240             if(size)
8241                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8242             else 
8243                 continueIfTrue(ifx);
8244             goto release;
8245         } else {
8246           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8247             // lit = 0, result = boolean(left)
8248             if(size)
8249                 pic16_emitcode(";XXX setb","c");
8250             pic16_toBoolean(right);
8251             if(size){
8252                 symbol *tlbl = newiTempLabel(NULL);
8253                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8254                 CLRC;
8255                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8256             } else {
8257                 genIfxJump (ifx,"a");
8258                 goto release;
8259             }
8260         }
8261         pic16_outBitC(result);
8262         goto release ;
8263     }
8264
8265     /* if left is same as result */
8266     if(pic16_sameRegs(AOP(result),AOP(left))){
8267       int know_W = -1;
8268       for(;size--; offset++,lit>>=8) {
8269         if(AOP_TYPE(right) == AOP_LIT){
8270           if((lit & 0xff) == 0)
8271             /*  or'ing with 0 has no effect */
8272             continue;
8273           else {
8274             int p = pic16_my_powof2(lit & 0xff);
8275             if(p>=0) {
8276               /* only one bit is set in the literal, so use a bsf instruction */
8277               pic16_emitpcode(POC_BSF,
8278                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8279             } else {
8280               if(know_W != (lit & 0xff))
8281                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8282               know_W = lit & 0xff;
8283               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8284             }
8285                     
8286           }
8287         } else {
8288           if (AOP_TYPE(left) == AOP_ACC) {
8289             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8290             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8291           } else {                  
8292             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8293             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8294
8295             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8296             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8297
8298           }
8299         }
8300       }
8301     } else {
8302         // left & result in different registers
8303         if(AOP_TYPE(result) == AOP_CRY){
8304             // result = bit
8305             // if(size), result in bit
8306             // if(!size && ifx), conditional oper: if(left | right)
8307             symbol *tlbl = newiTempLabel(NULL);
8308             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8309             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8310
8311
8312             if(size)
8313                 pic16_emitcode(";XXX setb","c");
8314             while(sizer--){
8315                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8316                 pic16_emitcode(";XXX orl","a,%s",
8317                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8318                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8319                 offset++;
8320             }
8321             if(size){
8322                 CLRC;
8323                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8324                 pic16_outBitC(result);
8325             } else if(ifx)
8326                 jmpTrueOrFalse(ifx, tlbl);
8327         } else for(;(size--);offset++){
8328           // normal case
8329           // result = left & right
8330           if(AOP_TYPE(right) == AOP_LIT){
8331             int t = (lit >> (offset*8)) & 0x0FFL;
8332             switch(t) { 
8333             case 0x00:
8334               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8335               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8336
8337               pic16_emitcode("movf","%s,w",
8338                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8339               pic16_emitcode("movwf","%s",
8340                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8341               break;
8342             default:
8343               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8344               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8345               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8346
8347               pic16_emitcode("movlw","0x%x",t);
8348               pic16_emitcode("iorwf","%s,w",
8349                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8350               pic16_emitcode("movwf","%s",
8351                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8352               
8353             }
8354             continue;
8355           }
8356
8357           // faster than result <- left, anl result,right
8358           // and better if result is SFR
8359           if (AOP_TYPE(left) == AOP_ACC) {
8360             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8361             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8362           } else {
8363             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8364             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8365
8366             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8367             pic16_emitcode("iorwf","%s,w",
8368                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8369           }
8370           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8371           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8372         }
8373     }
8374
8375 release :
8376     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8377     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8378     pic16_freeAsmop(result,NULL,ic,TRUE);     
8379 }
8380
8381 /*-----------------------------------------------------------------*/
8382 /* genXor - code for xclusive or                                   */
8383 /*-----------------------------------------------------------------*/
8384 static void genXor (iCode *ic, iCode *ifx)
8385 {
8386   operand *left, *right, *result;
8387   int size, offset=0;
8388   unsigned long lit = 0L;
8389
8390   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8391
8392   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8393   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8394   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8395
8396   /* if left is a literal & right is not ||
8397      if left needs acc & right does not */
8398   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8399       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8400     operand *tmp = right ;
8401     right = left;
8402     left = tmp;
8403   }
8404
8405   /* if result = right then exchange them */
8406   if(pic16_sameRegs(AOP(result),AOP(right))){
8407     operand *tmp = right ;
8408     right = left;
8409     left = tmp;
8410   }
8411
8412   /* if right is bit then exchange them */
8413   if (AOP_TYPE(right) == AOP_CRY &&
8414       AOP_TYPE(left) != AOP_CRY){
8415     operand *tmp = right ;
8416     right = left;
8417     left = tmp;
8418   }
8419   if(AOP_TYPE(right) == AOP_LIT)
8420     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8421
8422   size = AOP_SIZE(result);
8423
8424   // if(bit ^ yy)
8425   // xx = bit ^ yy;
8426   if (AOP_TYPE(left) == AOP_CRY){
8427     if(AOP_TYPE(right) == AOP_LIT){
8428       // c = bit & literal;
8429       if(lit>>1){
8430         // lit>>1  != 0 => result = 1
8431         if(AOP_TYPE(result) == AOP_CRY){
8432           if(size)
8433             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8434             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8435           else if(ifx)
8436             continueIfTrue(ifx);
8437           goto release;
8438         }
8439         pic16_emitcode("setb","c");
8440       } else{
8441         // lit == (0 or 1)
8442         if(lit == 0){
8443           // lit == 0, result = left
8444           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8445             goto release;
8446           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8447         } else{
8448           // lit == 1, result = not(left)
8449           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8450             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8451             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8452             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8453             goto release;
8454           } else {
8455             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8456             pic16_emitcode("cpl","c");
8457           }
8458         }
8459       }
8460
8461     } else {
8462       // right != literal
8463       symbol *tlbl = newiTempLabel(NULL);
8464       if (AOP_TYPE(right) == AOP_CRY){
8465         // c = bit ^ bit;
8466         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8467       }
8468       else{
8469         int sizer = AOP_SIZE(right);
8470         // c = bit ^ val
8471         // if val>>1 != 0, result = 1
8472         pic16_emitcode("setb","c");
8473         while(sizer){
8474           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8475           if(sizer == 1)
8476             // test the msb of the lsb
8477             pic16_emitcode("anl","a,#0xfe");
8478           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8479           sizer--;
8480         }
8481         // val = (0,1)
8482         pic16_emitcode("rrc","a");
8483       }
8484       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8485       pic16_emitcode("cpl","c");
8486       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8487     }
8488     // bit = c
8489     // val = c
8490     if(size)
8491       pic16_outBitC(result);
8492     // if(bit | ...)
8493     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8494       genIfxJump(ifx, "c");           
8495     goto release ;
8496   }
8497
8498   if(pic16_sameRegs(AOP(result),AOP(left))){
8499     /* if left is same as result */
8500     for(;size--; offset++) {
8501       if(AOP_TYPE(right) == AOP_LIT){
8502         int t  = (lit >> (offset*8)) & 0x0FFL;
8503         if(t == 0x00L)
8504           continue;
8505         else
8506           if (IS_AOP_PREG(left)) {
8507             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8508             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8509             pic16_aopPut(AOP(result),"a",offset);
8510           } else {
8511             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8512             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8513             pic16_emitcode("xrl","%s,%s",
8514                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8515                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8516           }
8517       } else {
8518         if (AOP_TYPE(left) == AOP_ACC)
8519           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8520         else {
8521           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8522           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8523 /*
8524           if (IS_AOP_PREG(left)) {
8525             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8526             pic16_aopPut(AOP(result),"a",offset);
8527           } else
8528             pic16_emitcode("xrl","%s,a",
8529                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8530 */
8531         }
8532       }
8533     }
8534   } else {
8535     // left & result in different registers
8536     if(AOP_TYPE(result) == AOP_CRY){
8537       // result = bit
8538       // if(size), result in bit
8539       // if(!size && ifx), conditional oper: if(left ^ right)
8540       symbol *tlbl = newiTempLabel(NULL);
8541       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8542       if(size)
8543         pic16_emitcode("setb","c");
8544       while(sizer--){
8545         if((AOP_TYPE(right) == AOP_LIT) &&
8546            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8547           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8548         } else {
8549           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8550           pic16_emitcode("xrl","a,%s",
8551                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8552         }
8553         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8554         offset++;
8555       }
8556       if(size){
8557         CLRC;
8558         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8559         pic16_outBitC(result);
8560       } else if(ifx)
8561         jmpTrueOrFalse(ifx, tlbl);
8562     } else for(;(size--);offset++){
8563       // normal case
8564       // result = left & right
8565       if(AOP_TYPE(right) == AOP_LIT){
8566         int t = (lit >> (offset*8)) & 0x0FFL;
8567         switch(t) { 
8568         case 0x00:
8569           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8570           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8571           pic16_emitcode("movf","%s,w",
8572                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8573           pic16_emitcode("movwf","%s",
8574                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8575           break;
8576         case 0xff:
8577           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8578           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8579           pic16_emitcode("comf","%s,w",
8580                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8581           pic16_emitcode("movwf","%s",
8582                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8583           break;
8584         default:
8585           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8586           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8587           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8588           pic16_emitcode("movlw","0x%x",t);
8589           pic16_emitcode("xorwf","%s,w",
8590                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8591           pic16_emitcode("movwf","%s",
8592                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8593
8594         }
8595         continue;
8596       }
8597
8598       // faster than result <- left, anl result,right
8599       // and better if result is SFR
8600       if (AOP_TYPE(left) == AOP_ACC) {
8601         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8602         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8603       } else {
8604         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8605         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8606         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8607         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8608       }
8609       if ( AOP_TYPE(result) != AOP_ACC){
8610         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8611         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8612       }
8613     }
8614   }
8615
8616   release :
8617     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8618   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8619   pic16_freeAsmop(result,NULL,ic,TRUE);     
8620 }
8621
8622 /*-----------------------------------------------------------------*/
8623 /* genInline - write the inline code out                           */
8624 /*-----------------------------------------------------------------*/
8625 static void genInline (iCode *ic)
8626 {
8627   char *buffer, *bp, *bp1;
8628     
8629         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8630
8631         _G.inLine += (!options.asmpeep);
8632
8633         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8634         strcpy(buffer,IC_INLINE(ic));
8635
8636 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8637
8638         /* emit each line as a code */
8639         while (*bp) {
8640                 if (*bp == '\n') {
8641                         *bp++ = '\0';
8642
8643                         if(*bp1)
8644                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8645                         bp1 = bp;
8646                 } else {
8647                         if (*bp == ':') {
8648                                 bp++;
8649                                 *bp = '\0';
8650                                 bp++;
8651
8652                                 /* print label, use this special format with NULL directive
8653                                  * to denote that the argument should not be indented with tab */
8654                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8655                                 bp1 = bp;
8656                         } else
8657                                 bp++;
8658                 }
8659         }
8660
8661         if ((bp1 != bp) && *bp1)
8662                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8663
8664
8665     Safe_free(buffer);
8666
8667     _G.inLine -= (!options.asmpeep);
8668 }
8669
8670 /*-----------------------------------------------------------------*/
8671 /* genRRC - rotate right with carry                                */
8672 /*-----------------------------------------------------------------*/
8673 static void genRRC (iCode *ic)
8674 {
8675   operand *left , *result ;
8676   int size, offset = 0, same;
8677
8678   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8679
8680   /* rotate right with carry */
8681   left = IC_LEFT(ic);
8682   result=IC_RESULT(ic);
8683   pic16_aopOp (left,ic,FALSE);
8684   pic16_aopOp (result,ic,FALSE);
8685
8686   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8687
8688   same = pic16_sameRegs(AOP(result),AOP(left));
8689
8690   size = AOP_SIZE(result);    
8691
8692   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8693
8694   /* get the lsb and put it into the carry */
8695   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8696
8697   offset = 0 ;
8698
8699   while(size--) {
8700
8701     if(same) {
8702       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8703     } else {
8704       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8706     }
8707
8708     offset++;
8709   }
8710
8711   pic16_freeAsmop(left,NULL,ic,TRUE);
8712   pic16_freeAsmop(result,NULL,ic,TRUE);
8713 }
8714
8715 /*-----------------------------------------------------------------*/
8716 /* genRLC - generate code for rotate left with carry               */
8717 /*-----------------------------------------------------------------*/
8718 static void genRLC (iCode *ic)
8719 {    
8720   operand *left , *result ;
8721   int size, offset = 0;
8722   int same;
8723
8724   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8725   /* rotate right with carry */
8726   left = IC_LEFT(ic);
8727   result=IC_RESULT(ic);
8728   pic16_aopOp (left,ic,FALSE);
8729   pic16_aopOp (result,ic,FALSE);
8730
8731   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8732
8733   same = pic16_sameRegs(AOP(result),AOP(left));
8734
8735   /* move it to the result */
8736   size = AOP_SIZE(result);    
8737
8738   /* get the msb and put it into the carry */
8739   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8740
8741   offset = 0 ;
8742
8743   while(size--) {
8744
8745     if(same) {
8746       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8747     } else {
8748       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8749       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8750     }
8751
8752     offset++;
8753   }
8754
8755
8756   pic16_freeAsmop(left,NULL,ic,TRUE);
8757   pic16_freeAsmop(result,NULL,ic,TRUE);
8758 }
8759
8760
8761 /* gpasm can get the highest order bit with HIGH/UPPER
8762  * so the following probably is not needed -- VR */
8763  
8764 /*-----------------------------------------------------------------*/
8765 /* genGetHbit - generates code get highest order bit               */
8766 /*-----------------------------------------------------------------*/
8767 static void genGetHbit (iCode *ic)
8768 {
8769     operand *left, *result;
8770     left = IC_LEFT(ic);
8771     result=IC_RESULT(ic);
8772     pic16_aopOp (left,ic,FALSE);
8773     pic16_aopOp (result,ic,FALSE);
8774
8775     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8776     /* get the highest order byte into a */
8777     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8778     if(AOP_TYPE(result) == AOP_CRY){
8779         pic16_emitcode("rlc","a");
8780         pic16_outBitC(result);
8781     }
8782     else{
8783         pic16_emitcode("rl","a");
8784         pic16_emitcode("anl","a,#0x01");
8785         pic16_outAcc(result);
8786     }
8787
8788
8789     pic16_freeAsmop(left,NULL,ic,TRUE);
8790     pic16_freeAsmop(result,NULL,ic,TRUE);
8791 }
8792
8793 #if 0
8794 /*-----------------------------------------------------------------*/
8795 /* AccRol - rotate left accumulator by known count                 */
8796 /*-----------------------------------------------------------------*/
8797 static void AccRol (int shCount)
8798 {
8799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800     shCount &= 0x0007;              // shCount : 0..7
8801     switch(shCount){
8802         case 0 :
8803             break;
8804         case 1 :
8805             pic16_emitcode("rl","a");
8806             break;
8807         case 2 :
8808             pic16_emitcode("rl","a");
8809             pic16_emitcode("rl","a");
8810             break;
8811         case 3 :
8812             pic16_emitcode("swap","a");
8813             pic16_emitcode("rr","a");
8814             break;
8815         case 4 :
8816             pic16_emitcode("swap","a");
8817             break;
8818         case 5 :
8819             pic16_emitcode("swap","a");
8820             pic16_emitcode("rl","a");
8821             break;
8822         case 6 :
8823             pic16_emitcode("rr","a");
8824             pic16_emitcode("rr","a");
8825             break;
8826         case 7 :
8827             pic16_emitcode("rr","a");
8828             break;
8829     }
8830 }
8831 #endif
8832
8833 /*-----------------------------------------------------------------*/
8834 /* AccLsh - left shift accumulator by known count                  */
8835 /*-----------------------------------------------------------------*/
8836 static void AccLsh (int shCount)
8837 {
8838         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839         switch(shCount){
8840                 case 0 :
8841                         return;
8842                         break;
8843                 case 1 :
8844                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8845                         break;
8846                 case 2 :
8847                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8848                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8849                         break;
8850                 case 3 :
8851                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8852                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8853                         break;
8854                 case 4 :
8855                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8856                         break;
8857                 case 5 :
8858                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8859                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8860                         break;
8861                 case 6 :
8862                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8863                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8864                         break;
8865                 case 7 :
8866                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8867                         break;
8868         }
8869
8870         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8871 }
8872
8873 /*-----------------------------------------------------------------*/
8874 /* AccRsh - right shift accumulator by known count                 */
8875 /*-----------------------------------------------------------------*/
8876 static void AccRsh (int shCount, int andmask)
8877 {
8878         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8879         switch(shCount){
8880                 case 0 :
8881                         return; break;
8882                 case 1 :
8883                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8884                         break;
8885                 case 2 :
8886                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8887                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8888                         break;
8889                 case 3 :
8890                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8891                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8892                         break;
8893                 case 4 :
8894                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8895                         break;
8896                 case 5 :
8897                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8898                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8899                         break;
8900                 case 6 :
8901                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8902                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8903                         break;
8904                 case 7 :
8905                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8906                         break;
8907         }
8908         
8909         if(andmask)
8910                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8911         else
8912                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8913 }
8914
8915 #if 0
8916 /*-----------------------------------------------------------------*/
8917 /* AccSRsh - signed right shift accumulator by known count                 */
8918 /*-----------------------------------------------------------------*/
8919 static void AccSRsh (int shCount)
8920 {
8921     symbol *tlbl ;
8922     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8923     if(shCount != 0){
8924         if(shCount == 1){
8925             pic16_emitcode("mov","c,acc.7");
8926             pic16_emitcode("rrc","a");
8927         } else if(shCount == 2){
8928             pic16_emitcode("mov","c,acc.7");
8929             pic16_emitcode("rrc","a");
8930             pic16_emitcode("mov","c,acc.7");
8931             pic16_emitcode("rrc","a");
8932         } else {
8933             tlbl = newiTempLabel(NULL);
8934             /* rotate right accumulator */
8935             AccRol(8 - shCount);
8936             /* and kill the higher order bits */
8937             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8938             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8939             pic16_emitcode("orl","a,#0x%02x",
8940                      (unsigned char)~SRMask[shCount]);
8941             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8942         }
8943     }
8944 }
8945 #endif
8946
8947 /*-----------------------------------------------------------------*/
8948 /* shiftR1Left2Result - shift right one byte from left to result   */
8949 /*-----------------------------------------------------------------*/
8950 static void shiftR1Left2ResultSigned (operand *left, int offl,
8951                                 operand *result, int offr,
8952                                 int shCount)
8953 {
8954   int same;
8955
8956   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8957
8958   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8959
8960   switch(shCount) {
8961   case 1:
8962     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8963     if(same) 
8964       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8965     else {
8966       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8967       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8968     }
8969
8970     break;
8971   case 2:
8972
8973     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8974     if(same) 
8975       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8976     else {
8977       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8978       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979     }
8980     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8981     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8982
8983     break;
8984
8985   case 3:
8986     if(same)
8987       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8988     else {
8989       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8990       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8991     }
8992
8993     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8994     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8995     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8996
8997     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8998     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8999
9000     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9001     break;
9002
9003   case 4:
9004     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9005     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
9006     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9007     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9008     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9009     break;
9010   case 5:
9011     if(same) {
9012       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9013     } else {
9014       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9015       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9016     }
9017     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9018     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9019     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9020     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9021     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9022     break;
9023
9024   case 6:
9025     if(same) {
9026       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9027       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9028       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9029       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9030       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9031       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9032     } else {
9033       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9034       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9035       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9037       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9038     }
9039     break;
9040
9041   case 7:
9042     if(same) {
9043       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9044       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9045       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9046       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9047     } else {
9048       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9050       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9051     }
9052
9053   default:
9054     break;
9055   }
9056 }
9057
9058 /*-----------------------------------------------------------------*/
9059 /* shiftR1Left2Result - shift right one byte from left to result   */
9060 /*-----------------------------------------------------------------*/
9061 static void shiftR1Left2Result (operand *left, int offl,
9062                                 operand *result, int offr,
9063                                 int shCount, int sign)
9064 {
9065   int same;
9066
9067   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9068
9069   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9070
9071   /* Copy the msb into the carry if signed. */
9072   if(sign) {
9073     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9074     return;
9075   }
9076
9077
9078
9079   switch(shCount) {
9080   case 1:
9081     emitCLRC;
9082     if(same) 
9083       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9084     else {
9085       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9086       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9087     }
9088     break;
9089   case 2:
9090     emitCLRC;
9091     if(same) {
9092       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9093     } else {
9094       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9095       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9096     }
9097     emitCLRC;
9098     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9099
9100     break;
9101   case 3:
9102     if(same)
9103       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9104     else {
9105       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9106       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9107     }
9108
9109     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9110     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9111     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9112     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9113     break;
9114       
9115   case 4:
9116     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9117     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9118     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9119     break;
9120
9121   case 5:
9122     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9123     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9124     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9125     //emitCLRC;
9126     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9127
9128     break;
9129   case 6:
9130
9131     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9133     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9134     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9135     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9136     break;
9137
9138   case 7:
9139
9140     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9141     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9142     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9143
9144     break;
9145
9146   default:
9147     break;
9148   }
9149 }
9150
9151 /*-----------------------------------------------------------------*/
9152 /* shiftL1Left2Result - shift left one byte from left to result    */
9153 /*-----------------------------------------------------------------*/
9154 static void shiftL1Left2Result (operand *left, int offl,
9155                                 operand *result, int offr, int shCount)
9156 {
9157   int same;
9158
9159   //    char *l;
9160   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9161
9162   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9163   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9164     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9165     //    MOVA(l);
9166     /* shift left accumulator */
9167     //AccLsh(shCount); // don't comment out just yet...
9168   //    pic16_aopPut(AOP(result),"a",offr);
9169
9170   switch(shCount) {
9171   case 1:
9172     /* Shift left 1 bit position */
9173     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9174     if(same) {
9175       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9176     } else {
9177       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9178       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9179     }
9180     break;
9181   case 2:
9182     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9183     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9184     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9185     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9186     break;
9187   case 3:
9188     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9189     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9190     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9191     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9192     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9193     break;
9194   case 4:
9195     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9196     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9197     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9198     break;
9199   case 5:
9200     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9201     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9202     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9203     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9204     break;
9205   case 6:
9206     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9210     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9211     break;
9212   case 7:
9213     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9214     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9215     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9216     break;
9217
9218   default:
9219     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9220   }
9221
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* movLeft2Result - move byte from left to result                  */
9226 /*-----------------------------------------------------------------*/
9227 static void movLeft2Result (operand *left, int offl,
9228                             operand *result, int offr)
9229 {
9230   char *l;
9231   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9232   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9233     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9234
9235     if (*l == '@' && (IS_AOP_PREG(result))) {
9236       pic16_emitcode("mov","a,%s",l);
9237       pic16_aopPut(AOP(result),"a",offr);
9238     } else {
9239       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9240       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9241     }
9242   }
9243 }
9244
9245 /*-----------------------------------------------------------------*/
9246 /* shiftL2Left2Result - shift left two bytes from left to result   */
9247 /*-----------------------------------------------------------------*/
9248 static void shiftL2Left2Result (operand *left, int offl,
9249                                 operand *result, int offr, int shCount)
9250 {
9251   int same = pic16_sameRegs(AOP(result), AOP(left));
9252   int i;
9253
9254   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9255
9256   if (same && (offl != offr)) { // shift bytes
9257     if (offr > offl) {
9258        for(i=1;i>-1;i--) {
9259          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9260          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9261        }
9262     } else { // just treat as different later on
9263                 same = 0;
9264     }
9265   }
9266
9267   if(same) {
9268     switch(shCount) {
9269     case 0:
9270       break;
9271     case 1:
9272     case 2:
9273     case 3:
9274
9275       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9276       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9277       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9278
9279       while(--shCount) {
9280                 emitCLRC;
9281                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9282                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9283       }
9284
9285       break;
9286     case 4:
9287     case 5:
9288       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9289       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9290       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9291       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9292       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9293       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9294       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9295       if(shCount >=5) {
9296                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9297                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9298       }
9299       break;
9300     case 6:
9301       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9302       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9304       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9305       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9306       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9307       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9308       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9309       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9310       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9311       break;
9312     case 7:
9313       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9314       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9315       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9316       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9317       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9318     }
9319
9320   } else {
9321     switch(shCount) {
9322     case 0:
9323       break;
9324     case 1:
9325     case 2:
9326     case 3:
9327       /* note, use a mov/add for the shift since the mov has a
9328          chance of getting optimized out */
9329       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9330       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9331       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9332       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9333       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9334
9335       while(--shCount) {
9336                 emitCLRC;
9337                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9338                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9339       }
9340       break;
9341
9342     case 4:
9343     case 5:
9344       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9345       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9346       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9347       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9348       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9349       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9350       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9351       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9352
9353
9354       if(shCount == 5) {
9355                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9356                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9357       }
9358       break;
9359     case 6:
9360       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9361       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9362       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9363       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9364
9365       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9366       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9367       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9368       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9369       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9370       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9371       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9372       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9373       break;
9374     case 7:
9375       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9376       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9377       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9378       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9379       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9380     }
9381   }
9382
9383 }
9384 /*-----------------------------------------------------------------*/
9385 /* shiftR2Left2Result - shift right two bytes from left to result  */
9386 /*-----------------------------------------------------------------*/
9387 static void shiftR2Left2Result (operand *left, int offl,
9388                                 operand *result, int offr,
9389                                 int shCount, int sign)
9390 {
9391   int same = pic16_sameRegs(AOP(result), AOP(left));
9392   int i;
9393   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9394
9395   if (same && (offl != offr)) { // shift right bytes
9396     if (offr < offl) {
9397        for(i=0;i<2;i++) {
9398          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9399          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9400        }
9401     } else { // just treat as different later on
9402                 same = 0;
9403     }
9404   }
9405
9406   switch(shCount) {
9407   case 0:
9408     break;
9409   case 1:
9410   case 2:
9411   case 3:
9412     if(sign)
9413       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9414     else
9415       emitCLRC;
9416
9417     if(same) {
9418       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9419       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9420     } else {
9421       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9422       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9423       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9424       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9425     }
9426
9427     while(--shCount) {
9428       if(sign)
9429                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9430       else
9431                 emitCLRC;
9432       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9433       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9434     }
9435     break;
9436   case 4:
9437   case 5:
9438     if(same) {
9439
9440       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9441       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9442       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9443
9444       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9445       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9446       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9447       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9448     } else {
9449       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9450       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9451       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9452
9453       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9454       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9455       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9456       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9457       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9458     }
9459
9460     if(shCount >=5) {
9461       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9462       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9463     }
9464
9465     if(sign) {
9466       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9467       pic16_emitpcode(POC_BTFSC, 
9468                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9469       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9470     }
9471
9472     break;
9473
9474   case 6:
9475     if(same) {
9476
9477       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9478       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9479
9480       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9481       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9482       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9483       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9484       if(sign) {
9485         pic16_emitpcode(POC_BTFSC, 
9486                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9487         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9488       }
9489       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9490       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9491       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9492       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9493     } else {
9494       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9495       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9496       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9497       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9498       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9499       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9500       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9501       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9502       if(sign) {
9503         pic16_emitpcode(POC_BTFSC, 
9504                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9505         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9506       }
9507       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9508       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9509
9510         
9511     }
9512
9513     break;
9514   case 7:
9515     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9516     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9517     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9518     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9519     if(sign) {
9520       emitSKPNC;
9521       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9522     } else 
9523       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9524   }
9525 }
9526
9527
9528 /*-----------------------------------------------------------------*/
9529 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9530 /*-----------------------------------------------------------------*/
9531 static void shiftLLeftOrResult (operand *left, int offl,
9532                                 operand *result, int offr, int shCount)
9533 {
9534     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9535
9536     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9537     /* shift left accumulator */
9538     AccLsh(shCount);
9539     /* or with result */
9540     /* back to result */
9541     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9542 }
9543
9544 /*-----------------------------------------------------------------*/
9545 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9546 /*-----------------------------------------------------------------*/
9547 static void shiftRLeftOrResult (operand *left, int offl,
9548                                 operand *result, int offr, int shCount)
9549 {
9550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9551     
9552     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9553     /* shift right accumulator */
9554     AccRsh(shCount, 1);
9555     /* or with result */
9556     /* back to result */
9557     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9558 }
9559
9560 /*-----------------------------------------------------------------*/
9561 /* genlshOne - left shift a one byte quantity by known count       */
9562 /*-----------------------------------------------------------------*/
9563 static void genlshOne (operand *result, operand *left, int shCount)
9564 {       
9565     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9566     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9567 }
9568
9569 /*-----------------------------------------------------------------*/
9570 /* genlshTwo - left shift two bytes by known amount != 0           */
9571 /*-----------------------------------------------------------------*/
9572 static void genlshTwo (operand *result,operand *left, int shCount)
9573 {
9574     int size;
9575     
9576     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9577     size = pic16_getDataSize(result);
9578
9579     /* if shCount >= 8 */
9580     if (shCount >= 8) {
9581         shCount -= 8 ;
9582
9583         if (size > 1){
9584             if (shCount)
9585                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9586             else 
9587                 movLeft2Result(left, LSB, result, MSB16);
9588         }
9589         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9590     }
9591
9592     /*  1 <= shCount <= 7 */
9593     else {  
9594         if(size == 1)
9595             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9596         else 
9597             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9598     }
9599 }
9600
9601 /*-----------------------------------------------------------------*/
9602 /* shiftLLong - shift left one long from left to result            */
9603 /* offr = LSB or MSB16                                             */
9604 /*-----------------------------------------------------------------*/
9605 static void shiftLLong (operand *left, operand *result, int offr )
9606 {
9607     int size = AOP_SIZE(result);
9608     int same = pic16_sameRegs(AOP(left),AOP(result));
9609         int i;
9610
9611     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9612
9613         if (same && (offr == MSB16)) { //shift one byte
9614                 for(i=size-1;i>=MSB16;i--) {
9615                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9616                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9617                 }
9618         } else {
9619                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9620         }
9621         
9622     if (size > LSB+offr ){
9623                 if (same) {
9624                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9625                 } else {
9626                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9627                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9628                 }
9629          }
9630
9631     if(size > MSB16+offr){
9632                 if (same) {
9633                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9634                 } else {
9635                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9636                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9637                 }
9638     }
9639
9640     if(size > MSB24+offr){
9641                 if (same) {
9642                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9643                 } else {
9644                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9645                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9646                 }
9647     }
9648
9649     if(size > MSB32+offr){
9650                 if (same) {
9651                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9652                 } else {
9653                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9654                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9655                 }
9656     }
9657     if(offr != LSB)
9658                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9659
9660 }
9661
9662 /*-----------------------------------------------------------------*/
9663 /* genlshFour - shift four byte by a known amount != 0             */
9664 /*-----------------------------------------------------------------*/
9665 static void genlshFour (operand *result, operand *left, int shCount)
9666 {
9667     int size;
9668
9669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9670     size = AOP_SIZE(result);
9671
9672     /* if shifting more that 3 bytes */
9673     if (shCount >= 24 ) {
9674         shCount -= 24;
9675         if (shCount)
9676             /* lowest order of left goes to the highest
9677             order of the destination */
9678             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9679         else
9680             movLeft2Result(left, LSB, result, MSB32);
9681
9682                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9683                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9684                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9685
9686         return;
9687     }
9688
9689     /* more than two bytes */
9690     else if ( shCount >= 16 ) {
9691         /* lower order two bytes goes to higher order two bytes */
9692         shCount -= 16;
9693         /* if some more remaining */
9694         if (shCount)
9695             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9696         else {
9697             movLeft2Result(left, MSB16, result, MSB32);
9698             movLeft2Result(left, LSB, result, MSB24);
9699         }
9700                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9701                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9702         return;
9703     }    
9704
9705     /* if more than 1 byte */
9706     else if ( shCount >= 8 ) {
9707         /* lower order three bytes goes to higher order  three bytes */
9708         shCount -= 8;
9709         if(size == 2){
9710             if(shCount)
9711                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9712             else
9713                 movLeft2Result(left, LSB, result, MSB16);
9714         }
9715         else{   /* size = 4 */
9716             if(shCount == 0){
9717                 movLeft2Result(left, MSB24, result, MSB32);
9718                 movLeft2Result(left, MSB16, result, MSB24);
9719                 movLeft2Result(left, LSB, result, MSB16);
9720                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9721             }
9722             else if(shCount == 1)
9723                 shiftLLong(left, result, MSB16);
9724             else{
9725                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9726                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9727                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9728                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9729             }
9730         }
9731     }
9732
9733     /* 1 <= shCount <= 7 */
9734     else if(shCount <= 3)
9735     { 
9736         shiftLLong(left, result, LSB);
9737         while(--shCount >= 1)
9738             shiftLLong(result, result, LSB);
9739     }
9740     /* 3 <= shCount <= 7, optimize */
9741     else{
9742         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9743         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9744         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9745     }
9746 }
9747
9748 /*-----------------------------------------------------------------*/
9749 /* genLeftShiftLiteral - left shifting by known count              */
9750 /*-----------------------------------------------------------------*/
9751 void pic16_genLeftShiftLiteral (operand *left,
9752                                  operand *right,
9753                                  operand *result,
9754                                  iCode *ic)
9755 {    
9756     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9757     int size;
9758
9759     FENTRY;
9760     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9761     pic16_freeAsmop(right,NULL,ic,TRUE);
9762
9763     pic16_aopOp(left,ic,FALSE);
9764     pic16_aopOp(result,ic,FALSE);
9765
9766     size = getSize(operandType(result));
9767
9768 #if VIEW_SIZE
9769     pic16_emitcode("; shift left ","result %d, left %d",size,
9770              AOP_SIZE(left));
9771 #endif
9772
9773     /* I suppose that the left size >= result size */
9774     if(shCount == 0){
9775         while(size--){
9776             movLeft2Result(left, size, result, size);
9777         }
9778     }
9779
9780     else if(shCount >= (size * 8))
9781         while(size--)
9782             pic16_aopPut(AOP(result),zero,size);
9783     else{
9784         switch (size) {
9785             case 1:
9786                 genlshOne (result,left,shCount);
9787                 break;
9788
9789             case 2:
9790             case 3:
9791                 genlshTwo (result,left,shCount);
9792                 break;
9793
9794             case 4:
9795                 genlshFour (result,left,shCount);
9796                 break;
9797         }
9798     }
9799     pic16_freeAsmop(left,NULL,ic,TRUE);
9800     pic16_freeAsmop(result,NULL,ic,TRUE);
9801 }
9802
9803 /*-----------------------------------------------------------------*
9804  * genMultiAsm - repeat assembly instruction for size of register.
9805  * if endian == 1, then the high byte (i.e base address + size of 
9806  * register) is used first else the low byte is used first;
9807  *-----------------------------------------------------------------*/
9808 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9809 {
9810
9811   int offset = 0;
9812
9813   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9814
9815   if(!reg)
9816     return;
9817
9818   if(!endian) {
9819     endian = 1;
9820   } else {
9821     endian = -1;
9822     offset = size-1;
9823   }
9824
9825   while(size--) {
9826     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9827     offset += endian;
9828   }
9829
9830 }
9831
9832 #if !(USE_GENERIC_SIGNED_SHIFT)
9833 /*-----------------------------------------------------------------*/
9834 /* genLeftShift - generates code for left shifting                 */
9835 /*-----------------------------------------------------------------*/
9836 static void genLeftShift (iCode *ic)
9837 {
9838   operand *left,*right, *result;
9839   int size, offset;
9840 //  char *l;
9841   symbol *tlbl , *tlbl1;
9842   pCodeOp *pctemp;
9843
9844   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9845
9846   right = IC_RIGHT(ic);
9847   left  = IC_LEFT(ic);
9848   result = IC_RESULT(ic);
9849
9850   pic16_aopOp(right,ic,FALSE);
9851
9852   /* if the shift count is known then do it 
9853      as efficiently as possible */
9854   if (AOP_TYPE(right) == AOP_LIT) {
9855     pic16_genLeftShiftLiteral (left,right,result,ic);
9856     return ;
9857   }
9858
9859   /* shift count is unknown then we have to form
9860    * a loop. Get the loop count in WREG : Note: we take
9861    * only the lower order byte since shifting
9862    * more than 32 bits make no sense anyway, ( the
9863    * largest size of an object can be only 32 bits ) */
9864   
9865   pic16_aopOp(left,ic,FALSE);
9866   pic16_aopOp(result,ic,FALSE);
9867
9868   /* now move the left to the result if they are not the
9869    * same, and if size > 1,
9870    * and if right is not same to result (!!!) -- VR */
9871   if (!pic16_sameRegs(AOP(left),AOP(result))
9872       && (AOP_SIZE(result) > 1)) {
9873
9874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9875
9876     size = AOP_SIZE(result);
9877     offset=0;
9878     while (size--) {
9879
9880 #if 0
9881       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9882       if (*l == '@' && (IS_AOP_PREG(result))) {
9883
9884           pic16_emitcode("mov","a,%s",l);
9885           pic16_aopPut(AOP(result),"a",offset);
9886       } else
9887 #endif
9888       {
9889         /* we don't know if left is a literal or a register, take care -- VR */
9890         mov2f(AOP(result), AOP(left), offset);
9891       }
9892       offset++;
9893     }
9894   }
9895
9896   size = AOP_SIZE(result);
9897
9898   /* if it is only one byte then */
9899   if (size == 1) {
9900     if(optimized_for_speed) {
9901       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9902       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9903       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9904       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9905       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9906       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9907       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9908       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9909       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9910       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9911       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9912       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9913     } else {
9914
9915       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9916
9917       tlbl = newiTempLabel(NULL);
9918
9919 #if 1
9920       /* this is already done, why change it? */
9921       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9922                 mov2f(AOP(result), AOP(left), 0);
9923       }
9924 #endif
9925
9926       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9927       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9928       pic16_emitpLabel(tlbl->key);
9929       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9930       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9931       emitSKPC;
9932       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9933     }
9934     goto release ;
9935   }
9936     
9937   if (pic16_sameRegs(AOP(left),AOP(result))) {
9938
9939     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9940     
9941     tlbl = newiTempLabel(NULL);
9942     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9943     genMultiAsm(POC_RRCF, result, size,1);
9944     pic16_emitpLabel(tlbl->key);
9945     genMultiAsm(POC_RLCF, result, size,0);
9946     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9947     emitSKPC;
9948     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9949     goto release;
9950   }
9951
9952   //tlbl = newiTempLabel(NULL);
9953   //offset = 0 ;   
9954   //tlbl1 = newiTempLabel(NULL);
9955
9956   //reAdjustPreg(AOP(result));    
9957     
9958   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9959   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9960   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9961   //MOVA(l);
9962   //pic16_emitcode("add","a,acc");         
9963   //pic16_aopPut(AOP(result),"a",offset++);
9964   //while (--size) {
9965   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9966   //  MOVA(l);
9967   //  pic16_emitcode("rlc","a");         
9968   //  pic16_aopPut(AOP(result),"a",offset++);
9969   //}
9970   //reAdjustPreg(AOP(result));
9971
9972   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9973   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9974
9975
9976   tlbl = newiTempLabel(NULL);
9977   tlbl1= newiTempLabel(NULL);
9978
9979   size = AOP_SIZE(result);
9980   offset = 1;
9981
9982   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9983
9984   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9985
9986   /* offset should be 0, 1 or 3 */
9987   
9988   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9989   emitSKPNZ;
9990   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9991
9992   pic16_emitpcode(POC_MOVWF, pctemp);
9993
9994
9995   pic16_emitpLabel(tlbl->key);
9996
9997   emitCLRC;
9998   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9999   while(--size)
10000     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10001
10002   pic16_emitpcode(POC_DECFSZ,  pctemp);
10003   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10004   pic16_emitpLabel(tlbl1->key);
10005
10006   pic16_popReleaseTempReg(pctemp,1);
10007
10008
10009  release:
10010   pic16_freeAsmop (right,NULL,ic,TRUE);
10011   pic16_freeAsmop(left,NULL,ic,TRUE);
10012   pic16_freeAsmop(result,NULL,ic,TRUE);
10013 }
10014 #endif
10015
10016
10017 #if 0
10018 #error old code (left here for reference)
10019 /*-----------------------------------------------------------------*/
10020 /* genLeftShift - generates code for left shifting                 */
10021 /*-----------------------------------------------------------------*/
10022 static void genLeftShift (iCode *ic)
10023 {
10024   operand *left,*right, *result;
10025   int size, offset;
10026   char *l;
10027   symbol *tlbl , *tlbl1;
10028   pCodeOp *pctemp;
10029
10030   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10031
10032   right = IC_RIGHT(ic);
10033   left  = IC_LEFT(ic);
10034   result = IC_RESULT(ic);
10035
10036   pic16_aopOp(right,ic,FALSE);
10037
10038   /* if the shift count is known then do it 
10039      as efficiently as possible */
10040   if (AOP_TYPE(right) == AOP_LIT) {
10041     pic16_genLeftShiftLiteral (left,right,result,ic);
10042     return ;
10043   }
10044
10045   /* shift count is unknown then we have to form 
10046      a loop get the loop count in B : Note: we take
10047      only the lower order byte since shifting
10048      more that 32 bits make no sense anyway, ( the
10049      largest size of an object can be only 32 bits ) */  
10050
10051     
10052   pic16_aopOp(left,ic,FALSE);
10053   pic16_aopOp(result,ic,FALSE);
10054
10055   /* now move the left to the result if they are not the
10056      same */
10057   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10058       AOP_SIZE(result) > 1) {
10059
10060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10061
10062     size = AOP_SIZE(result);
10063     offset=0;
10064     while (size--) {
10065       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10066       if (*l == '@' && (IS_AOP_PREG(result))) {
10067
10068         pic16_emitcode("mov","a,%s",l);
10069         pic16_aopPut(AOP(result),"a",offset);
10070       } else {
10071
10072         /* we don't know if left is a literal or a register, take care -- VR */
10073         mov2f(AOP(result), AOP(left), offset);
10074       }
10075       offset++;
10076     }
10077   }
10078
10079   size = AOP_SIZE(result);
10080
10081   /* if it is only one byte then */
10082   if (size == 1) {
10083     if(optimized_for_speed) {
10084       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10085       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10086       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10087       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10088       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10089       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10090       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10091       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10092       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10093       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10094       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10095       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10096     } else {
10097
10098       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10099
10100       tlbl = newiTempLabel(NULL);
10101       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10102                 mov2f(AOP(result), AOP(left), 0);
10103                 
10104 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10105 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10106       }
10107
10108       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10109       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10110       pic16_emitpLabel(tlbl->key);
10111       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10112       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10113       emitSKPC;
10114       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10115     }
10116     goto release ;
10117   }
10118     
10119   if (pic16_sameRegs(AOP(left),AOP(result))) {
10120
10121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10122     
10123     tlbl = newiTempLabel(NULL);
10124     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10125     genMultiAsm(POC_RRCF, result, size,1);
10126     pic16_emitpLabel(tlbl->key);
10127     genMultiAsm(POC_RLCF, result, size,0);
10128     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10129     emitSKPC;
10130     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10131     goto release;
10132   }
10133
10134   //tlbl = newiTempLabel(NULL);
10135   //offset = 0 ;   
10136   //tlbl1 = newiTempLabel(NULL);
10137
10138   //reAdjustPreg(AOP(result));    
10139     
10140   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10141   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10142   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10143   //MOVA(l);
10144   //pic16_emitcode("add","a,acc");         
10145   //pic16_aopPut(AOP(result),"a",offset++);
10146   //while (--size) {
10147   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10148   //  MOVA(l);
10149   //  pic16_emitcode("rlc","a");         
10150   //  pic16_aopPut(AOP(result),"a",offset++);
10151   //}
10152   //reAdjustPreg(AOP(result));
10153
10154   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10155   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10156
10157
10158   tlbl = newiTempLabel(NULL);
10159   tlbl1= newiTempLabel(NULL);
10160
10161   size = AOP_SIZE(result);
10162   offset = 1;
10163
10164   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10165
10166   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10167
10168   /* offset should be 0, 1 or 3 */
10169   
10170   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10171   emitSKPNZ;
10172   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10173
10174   pic16_emitpcode(POC_MOVWF, pctemp);
10175
10176
10177   pic16_emitpLabel(tlbl->key);
10178
10179   emitCLRC;
10180   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10181   while(--size)
10182     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10183
10184   pic16_emitpcode(POC_DECFSZ,  pctemp);
10185   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10186   pic16_emitpLabel(tlbl1->key);
10187
10188   pic16_popReleaseTempReg(pctemp,1);
10189
10190
10191  release:
10192   pic16_freeAsmop (right,NULL,ic,TRUE);
10193   pic16_freeAsmop(left,NULL,ic,TRUE);
10194   pic16_freeAsmop(result,NULL,ic,TRUE);
10195 }
10196 #endif
10197
10198 /*-----------------------------------------------------------------*/
10199 /* genrshOne - right shift a one byte quantity by known count      */
10200 /*-----------------------------------------------------------------*/
10201 static void genrshOne (operand *result, operand *left,
10202                        int shCount, int sign)
10203 {
10204     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10205     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10206 }
10207
10208 /*-----------------------------------------------------------------*/
10209 /* genrshTwo - right shift two bytes by known amount != 0          */
10210 /*-----------------------------------------------------------------*/
10211 static void genrshTwo (operand *result,operand *left,
10212                        int shCount, int sign)
10213 {
10214   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10215   /* if shCount >= 8 */
10216   if (shCount >= 8) {
10217     shCount -= 8 ;
10218     if (shCount)
10219       shiftR1Left2Result(left, MSB16, result, LSB,
10220                          shCount, sign);
10221     else
10222       movLeft2Result(left, MSB16, result, LSB);
10223
10224     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10225
10226     if(sign) {
10227       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10228       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10229     }
10230   }
10231
10232   /*  1 <= shCount <= 7 */
10233   else
10234     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10235 }
10236
10237 /*-----------------------------------------------------------------*/
10238 /* shiftRLong - shift right one long from left to result           */
10239 /* offl = LSB or MSB16                                             */
10240 /*-----------------------------------------------------------------*/
10241 static void shiftRLong (operand *left, int offl,
10242                         operand *result, int sign)
10243 {
10244     int size = AOP_SIZE(result);
10245     int same = pic16_sameRegs(AOP(left),AOP(result));
10246     int i;
10247     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10248
10249         if (same && (offl == MSB16)) { //shift one byte right
10250                 for(i=MSB16;i<size;i++) {
10251                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10252                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10253                 }
10254         }
10255
10256     if(sign)
10257                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10258         else
10259                 emitCLRC;
10260
10261         if (same) {
10262                 if (offl == LSB)
10263                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10264         } else {
10265         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10266         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10267         }
10268
10269     if(offl == MSB16) {
10270         /* add sign of "a" */
10271         pic16_addSign(result, MSB32, sign);
10272         }
10273
10274         if (same) {
10275         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10276         } else {
10277         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10278         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10279         }
10280         
10281         if (same) {
10282         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10283         } else {
10284         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10285         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10286         }
10287
10288         if (same) {
10289         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10290         } else {
10291         if(offl == LSB){
10292                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10293                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10294         }
10295         }
10296 }
10297
10298 /*-----------------------------------------------------------------*/
10299 /* genrshFour - shift four byte by a known amount != 0             */
10300 /*-----------------------------------------------------------------*/
10301 static void genrshFour (operand *result, operand *left,
10302                         int shCount, int sign)
10303 {
10304   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10305   /* if shifting more that 3 bytes */
10306   if(shCount >= 24 ) {
10307     shCount -= 24;
10308     if(shCount)
10309       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10310     else
10311       movLeft2Result(left, MSB32, result, LSB);
10312
10313     pic16_addSign(result, MSB16, sign);
10314   }
10315   else if(shCount >= 16){
10316     shCount -= 16;
10317     if(shCount)
10318       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10319     else{
10320       movLeft2Result(left, MSB24, result, LSB);
10321       movLeft2Result(left, MSB32, result, MSB16);
10322     }
10323     pic16_addSign(result, MSB24, sign);
10324   }
10325   else if(shCount >= 8){
10326     shCount -= 8;
10327     if(shCount == 1)
10328       shiftRLong(left, MSB16, result, sign);
10329     else if(shCount == 0){
10330       movLeft2Result(left, MSB16, result, LSB);
10331       movLeft2Result(left, MSB24, result, MSB16);
10332       movLeft2Result(left, MSB32, result, MSB24);
10333       pic16_addSign(result, MSB32, sign);
10334     }
10335     else{ //shcount >= 2
10336       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10337       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10338       /* the last shift is signed */
10339       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10340       pic16_addSign(result, MSB32, sign);
10341     }
10342   }
10343   else{   /* 1 <= shCount <= 7 */
10344     if(shCount <= 2){
10345       shiftRLong(left, LSB, result, sign);
10346       if(shCount == 2)
10347         shiftRLong(result, LSB, result, sign);
10348     }
10349     else{
10350       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10351       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10352       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10353     }
10354   }
10355 }
10356
10357 /*-----------------------------------------------------------------*/
10358 /* genRightShiftLiteral - right shifting by known count            */
10359 /*-----------------------------------------------------------------*/
10360 static void genRightShiftLiteral (operand *left,
10361                                   operand *right,
10362                                   operand *result,
10363                                   iCode *ic,
10364                                   int sign)
10365 {    
10366   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10367   int lsize,res_size;
10368
10369   pic16_freeAsmop(right,NULL,ic,TRUE);
10370
10371   pic16_aopOp(left,ic,FALSE);
10372   pic16_aopOp(result,ic,FALSE);
10373
10374   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10375
10376 #if VIEW_SIZE
10377   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10378                  AOP_SIZE(left));
10379 #endif
10380
10381   lsize = pic16_getDataSize(left);
10382   res_size = pic16_getDataSize(result);
10383   /* test the LEFT size !!! */
10384
10385   /* I suppose that the left size >= result size */
10386   if(shCount == 0){
10387     while(res_size--)
10388       movLeft2Result(left, lsize, result, res_size);
10389   }
10390
10391   else if(shCount >= (lsize * 8)){
10392
10393     if(res_size == 1) {
10394       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10395       if(sign) {
10396         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10397         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10398       }
10399     } else {
10400
10401       if(sign) {
10402         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10403         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10404         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10405         while(res_size--)
10406           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10407
10408       } else {
10409
10410         while(res_size--)
10411           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10412       }
10413     }
10414   } else {
10415
10416     switch (res_size) {
10417     case 1:
10418       genrshOne (result,left,shCount,sign);
10419       break;
10420
10421     case 2:
10422       genrshTwo (result,left,shCount,sign);
10423       break;
10424
10425     case 4:
10426       genrshFour (result,left,shCount,sign);
10427       break;
10428     default :
10429       break;
10430     }
10431
10432   }
10433
10434   pic16_freeAsmop(left,NULL,ic,TRUE);
10435   pic16_freeAsmop(result,NULL,ic,TRUE);
10436 }
10437
10438 #if !(USE_GENERIC_SIGNED_SHIFT)
10439 /*-----------------------------------------------------------------*/
10440 /* genSignedRightShift - right shift of signed number              */
10441 /*-----------------------------------------------------------------*/
10442 static void genSignedRightShift (iCode *ic)
10443 {
10444   operand *right, *left, *result;
10445   int size, offset;
10446   //  char *l;
10447   symbol *tlbl, *tlbl1 ;
10448   pCodeOp *pctemp;
10449
10450   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10451
10452   /* we do it the hard way put the shift count in b
10453      and loop thru preserving the sign */
10454   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10455
10456   right = IC_RIGHT(ic);
10457   left  = IC_LEFT(ic);
10458   result = IC_RESULT(ic);
10459
10460   pic16_aopOp(right,ic,FALSE);  
10461   pic16_aopOp(left,ic,FALSE);
10462   pic16_aopOp(result,ic,FALSE);
10463
10464
10465   if ( AOP_TYPE(right) == AOP_LIT) {
10466     genRightShiftLiteral (left,right,result,ic,1);
10467     return ;
10468   }
10469   /* shift count is unknown then we have to form 
10470      a loop get the loop count in B : Note: we take
10471      only the lower order byte since shifting
10472      more that 32 bits make no sense anyway, ( the
10473      largest size of an object can be only 32 bits ) */  
10474
10475   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10476   //pic16_emitcode("inc","b");
10477   //pic16_freeAsmop (right,NULL,ic,TRUE);
10478   //pic16_aopOp(left,ic,FALSE);
10479   //pic16_aopOp(result,ic,FALSE);
10480
10481   /* now move the left to the result if they are not the
10482      same */
10483   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10484       AOP_SIZE(result) > 1) {
10485
10486     size = AOP_SIZE(result);
10487     offset=0;
10488     while (size--) { 
10489       /*
10490         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10491         if (*l == '@' && IS_AOP_PREG(result)) {
10492
10493         pic16_emitcode("mov","a,%s",l);
10494         pic16_aopPut(AOP(result),"a",offset);
10495         } else
10496         pic16_aopPut(AOP(result),l,offset);
10497       */
10498       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10499       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10500
10501       offset++;
10502     }
10503   }
10504
10505   /* mov the highest order bit to OVR */    
10506   tlbl = newiTempLabel(NULL);
10507   tlbl1= newiTempLabel(NULL);
10508
10509   size = AOP_SIZE(result);
10510   offset = size - 1;
10511
10512   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10513
10514   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10515
10516   /* offset should be 0, 1 or 3 */
10517   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10518   emitSKPNZ;
10519   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10520
10521   pic16_emitpcode(POC_MOVWF, pctemp);
10522
10523
10524   pic16_emitpLabel(tlbl->key);
10525
10526   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10527   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10528
10529   while(--size) {
10530     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10531   }
10532
10533   pic16_emitpcode(POC_DECFSZ,  pctemp);
10534   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10535   pic16_emitpLabel(tlbl1->key);
10536
10537   pic16_popReleaseTempReg(pctemp,1);
10538 #if 0
10539   size = AOP_SIZE(result);
10540   offset = size - 1;
10541   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10542   pic16_emitcode("rlc","a");
10543   pic16_emitcode("mov","ov,c");
10544   /* if it is only one byte then */
10545   if (size == 1) {
10546     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10547     MOVA(l);
10548     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10549     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10550     pic16_emitcode("mov","c,ov");
10551     pic16_emitcode("rrc","a");
10552     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10553     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10554     pic16_aopPut(AOP(result),"a",0);
10555     goto release ;
10556   }
10557
10558   reAdjustPreg(AOP(result));
10559   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10560   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10561   pic16_emitcode("mov","c,ov");
10562   while (size--) {
10563     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10564     MOVA(l);
10565     pic16_emitcode("rrc","a");         
10566     pic16_aopPut(AOP(result),"a",offset--);
10567   }
10568   reAdjustPreg(AOP(result));
10569   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10570   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10571
10572  release:
10573 #endif
10574
10575   pic16_freeAsmop(left,NULL,ic,TRUE);
10576   pic16_freeAsmop(result,NULL,ic,TRUE);
10577   pic16_freeAsmop(right,NULL,ic,TRUE);
10578 }
10579 #endif
10580
10581 #if !(USE_GENERIC_SIGNED_SHIFT)
10582 #warning This implementation of genRightShift() is incomplete!
10583 /*-----------------------------------------------------------------*/
10584 /* genRightShift - generate code for right shifting                */
10585 /*-----------------------------------------------------------------*/
10586 static void genRightShift (iCode *ic)
10587 {
10588     operand *right, *left, *result;
10589     sym_link *letype ;
10590     int size, offset;
10591     char *l;
10592     symbol *tlbl, *tlbl1 ;
10593
10594     /* if signed then we do it the hard way preserve the
10595     sign bit moving it inwards */
10596     letype = getSpec(operandType(IC_LEFT(ic)));
10597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10598
10599     if (!SPEC_USIGN(letype)) {
10600         genSignedRightShift (ic);
10601         return ;
10602     }
10603
10604     /* signed & unsigned types are treated the same : i.e. the
10605     signed is NOT propagated inwards : quoting from the
10606     ANSI - standard : "for E1 >> E2, is equivalent to division
10607     by 2**E2 if unsigned or if it has a non-negative value,
10608     otherwise the result is implementation defined ", MY definition
10609     is that the sign does not get propagated */
10610
10611     right = IC_RIGHT(ic);
10612     left  = IC_LEFT(ic);
10613     result = IC_RESULT(ic);
10614
10615     pic16_aopOp(right,ic,FALSE);
10616
10617     /* if the shift count is known then do it 
10618     as efficiently as possible */
10619     if (AOP_TYPE(right) == AOP_LIT) {
10620         genRightShiftLiteral (left,right,result,ic, 0);
10621         return ;
10622     }
10623
10624     /* shift count is unknown then we have to form 
10625     a loop get the loop count in B : Note: we take
10626     only the lower order byte since shifting
10627     more that 32 bits make no sense anyway, ( the
10628     largest size of an object can be only 32 bits ) */  
10629
10630     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10631     pic16_emitcode("inc","b");
10632     pic16_aopOp(left,ic,FALSE);
10633     pic16_aopOp(result,ic,FALSE);
10634
10635     /* now move the left to the result if they are not the
10636     same */
10637     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10638         AOP_SIZE(result) > 1) {
10639
10640         size = AOP_SIZE(result);
10641         offset=0;
10642         while (size--) {
10643             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10644             if (*l == '@' && IS_AOP_PREG(result)) {
10645
10646                 pic16_emitcode("mov","a,%s",l);
10647                 pic16_aopPut(AOP(result),"a",offset);
10648             } else
10649                 pic16_aopPut(AOP(result),l,offset);
10650             offset++;
10651         }
10652     }
10653
10654     tlbl = newiTempLabel(NULL);
10655     tlbl1= newiTempLabel(NULL);
10656     size = AOP_SIZE(result);
10657     offset = size - 1;
10658
10659     /* if it is only one byte then */
10660     if (size == 1) {
10661
10662       tlbl = newiTempLabel(NULL);
10663       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10664         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10665         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10666       }
10667
10668       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10669       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10670       pic16_emitpLabel(tlbl->key);
10671       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10672       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10673       emitSKPC;
10674       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10675
10676       goto release ;
10677     }
10678
10679     reAdjustPreg(AOP(result));
10680     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10681     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10682     CLRC;
10683     while (size--) {
10684         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10685         MOVA(l);
10686         pic16_emitcode("rrc","a");         
10687         pic16_aopPut(AOP(result),"a",offset--);
10688     }
10689     reAdjustPreg(AOP(result));
10690
10691     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10692     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10693
10694 release:
10695     pic16_freeAsmop(left,NULL,ic,TRUE);
10696     pic16_freeAsmop (right,NULL,ic,TRUE);
10697     pic16_freeAsmop(result,NULL,ic,TRUE);
10698 }
10699 #endif
10700
10701 #if (USE_GENERIC_SIGNED_SHIFT)
10702 /*-----------------------------------------------------------------*/
10703 /* genGenericShift - generates code for left or right shifting     */
10704 /*-----------------------------------------------------------------*/
10705 static void genGenericShift (iCode *ic, int isShiftLeft) {
10706   operand *left,*right, *result;
10707   int offset;
10708   int sign, signedCount;
10709   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10710   PIC_OPCODE pos_shift, neg_shift;
10711
10712   FENTRY;
10713
10714   right = IC_RIGHT(ic);
10715   left  = IC_LEFT(ic);
10716   result = IC_RESULT(ic);
10717
10718   pic16_aopOp(right,ic,FALSE);
10719   pic16_aopOp(left,ic,FALSE);
10720   pic16_aopOp(result,ic,FALSE);
10721
10722   sign = !SPEC_USIGN(operandType (left));
10723   signedCount = !SPEC_USIGN(operandType (right));
10724
10725   /* if the shift count is known then do it 
10726      as efficiently as possible */
10727   if (AOP_TYPE(right) == AOP_LIT) {
10728     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10729     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10730     // we should modify right->aopu.aop_lit here!
10731     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10732     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10733     if (isShiftLeft)
10734       pic16_genLeftShiftLiteral (left,right,result,ic);
10735     else
10736       genRightShiftLiteral (left,right,result,ic, sign);
10737
10738     goto release;
10739   } // if (right is literal)
10740
10741   /* shift count is unknown then we have to form a loop.
10742    * Note: we take only the lower order byte since shifting
10743    * more than 32 bits make no sense anyway, ( the
10744    * largest size of an object can be only 32 bits )
10745    * Note: we perform arithmetic shifts if the left operand is
10746    * signed and we do an (effective) right shift, i. e. we
10747    * shift in the sign bit from the left. */
10748    
10749   label_complete = newiTempLabel ( NULL );
10750   label_loop_pos = newiTempLabel ( NULL );
10751   label_loop_neg = NULL;
10752   label_negative = NULL;
10753   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10754   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10755
10756   if (signedCount) {
10757     // additional labels needed
10758     label_loop_neg = newiTempLabel ( NULL );
10759     label_negative = newiTempLabel ( NULL );
10760   } // if
10761
10762   // copy source to result -- this will effectively truncate the left operand to the size of result!
10763   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10764   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10765   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10766     mov2f (AOP(result),AOP(left), offset);
10767   } // for
10768
10769   // if result is longer than left, fill with zeros (or sign)
10770   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10771     if (sign && AOP_SIZE(left) > 0) {
10772       // shift signed operand -- fill with sign
10773       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10774       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10775       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10776       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10777         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10778       } // for
10779     } else {
10780       // shift unsigned operand -- fill result with zeros
10781       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10782         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10783       } // for
10784     }
10785   } // if (size mismatch)
10786
10787   pic16_mov2w (AOP(right), 0);
10788   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10789   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10790   
10791 #if 0
10792   // perform a shift by one (shift count is positive)
10793   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10794   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10795   pic16_emitpLabel (label_loop_pos->key);
10796   emitCLRC;
10797   if (sign && (pos_shift == POC_RRCF)) {
10798     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10799     emitSETC;
10800   } // if
10801   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10802   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10803   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10804 #else
10805   // perform a shift by one (shift count is positive)
10806   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10807   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10808   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10809   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10810   emitCLRC;
10811   pic16_emitpLabel (label_loop_pos->key);
10812   if (sign && (pos_shift == POC_RRCF)) {
10813     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10814     emitSETC;
10815   } // if
10816   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10817   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10818   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10819   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10820 #endif
10821
10822   if (signedCount) {
10823     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10824
10825     pic16_emitpLabel (label_negative->key);
10826     // perform a shift by -1 (shift count is negative)
10827     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10828     emitCLRC;
10829     pic16_emitpLabel (label_loop_neg->key);
10830     if (sign && (neg_shift == POC_RRCF)) {
10831       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10832       emitSETC;
10833     } // if
10834     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10835     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10836     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10837     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10838   } // if (signedCount)
10839
10840   pic16_emitpLabel (label_complete->key);
10841
10842 release:
10843   pic16_freeAsmop (right,NULL,ic,TRUE);
10844   pic16_freeAsmop(left,NULL,ic,TRUE);
10845   pic16_freeAsmop(result,NULL,ic,TRUE);
10846 }
10847
10848 static void genLeftShift (iCode *ic) {
10849   genGenericShift (ic, 1);
10850 }
10851
10852 static void genRightShift (iCode *ic) {
10853   genGenericShift (ic, 0);
10854 }
10855 #endif
10856
10857
10858 void pic16_loadFSR0(operand *op)
10859 {
10860         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10861 }
10862
10863 /*-----------------------------------------------------------------*/
10864 /* genUnpackBits - generates code for unpacking bits               */
10865 /*-----------------------------------------------------------------*/
10866 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10867 {    
10868   int shCnt ;
10869   int rlen = 0 ;
10870   sym_link *etype, *letype;
10871   int blen=0, bstr=0;
10872   int lbstr;
10873   int offset = 0 ;
10874
10875     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10876     etype = getSpec(operandType(result));
10877     letype = getSpec(operandType(left));
10878     
10879 //    if(IS_BITFIELD(etype)) {
10880       blen = SPEC_BLEN(etype);
10881       bstr = SPEC_BSTR(etype);
10882 //    }
10883
10884     lbstr = SPEC_BSTR( letype );
10885
10886 #if 1
10887     if((blen == 1) && (bstr < 8)) {
10888       /* it is a single bit, so use the appropriate bit instructions */
10889       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10890
10891       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10892       
10893       if((ptype == POINTER) && (result)) {
10894         /* workaround to reduce the extra lfsr instruction */
10895         pic16_emitpcode(POC_BTFSC,
10896               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10897       } else {
10898         pic16_emitpcode(POC_BTFSC,
10899               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10900       }
10901         
10902       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10903
10904       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10905       return;
10906     }
10907
10908 #endif
10909
10910         /* the following call to pic16_loadFSR0 is temporary until
10911          * optimization to handle single bit assignments is added
10912          * to the function. Until then use the old safe way! -- VR */
10913         pic16_loadFSR0( left );
10914  
10915         /* read the first byte  */
10916         switch (ptype) {
10917                 case POINTER:
10918                 case IPOINTER:
10919                 case PPOINTER:
10920                 case FPOINTER:
10921                 case GPOINTER:
10922                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10923                         break;
10924                 case CPOINTER:
10925                         pic16_emitcode("clr","a");
10926                         pic16_emitcode("movc","a","@a+dptr");
10927                         break;
10928         }
10929         
10930
10931         /* if we have bitdisplacement then it fits   */
10932         /* into this byte completely or if length is */
10933         /* less than a byte                          */
10934         if ((shCnt = SPEC_BSTR(etype)) || 
10935                 (SPEC_BLEN(etype) <= 8))  {
10936
10937                 /* shift right acc */
10938                 AccRsh(shCnt, 0);
10939
10940                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10941                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10942
10943 /* VR -- normally I would use the following, but since we use the hack,
10944  * to avoid the masking from AccRsh, why not mask it right now? */
10945
10946 /*
10947                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10948 */
10949
10950                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10951           return ;
10952         }
10953
10954
10955
10956         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10957         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10958         exit(-1);
10959
10960     /* bit field did not fit in a byte  */
10961     rlen = SPEC_BLEN(etype) - 8;
10962     pic16_aopPut(AOP(result),"a",offset++);
10963
10964     while (1)  {
10965
10966         switch (ptype) {
10967         case POINTER:
10968         case IPOINTER:
10969             pic16_emitcode("inc","%s",rname);
10970             pic16_emitcode("mov","a,@%s",rname);
10971             break;
10972             
10973         case PPOINTER:
10974             pic16_emitcode("inc","%s",rname);
10975             pic16_emitcode("movx","a,@%s",rname);
10976             break;
10977
10978         case FPOINTER:
10979             pic16_emitcode("inc","dptr");
10980             pic16_emitcode("movx","a,@dptr");
10981             break;
10982             
10983         case CPOINTER:
10984             pic16_emitcode("clr","a");
10985             pic16_emitcode("inc","dptr");
10986             pic16_emitcode("movc","a","@a+dptr");
10987             break;
10988             
10989         case GPOINTER:
10990             pic16_emitcode("inc","dptr");
10991             pic16_emitcode("lcall","__gptrget");
10992             break;
10993         }
10994
10995         rlen -= 8;            
10996         /* if we are done */
10997         if ( rlen <= 0 )
10998             break ;
10999         
11000         pic16_aopPut(AOP(result),"a",offset++);
11001                               
11002     }
11003     
11004     if (rlen) {
11005         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11006         pic16_aopPut(AOP(result),"a",offset);          
11007     }
11008     
11009     return ;
11010 }
11011
11012
11013 static void genDataPointerGet(operand *left,
11014                               operand *result,
11015                               iCode *ic)
11016 {
11017   int size, offset = 0, leoffset=0 ;
11018
11019         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11020         pic16_aopOp(result, ic, FALSE);
11021
11022         size = AOP_SIZE(result);
11023 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11024
11025
11026 #if 0
11027         /* The following tests may save a redudant movff instruction when
11028          * accessing unions */
11029          
11030         /* if they are the same */
11031         if (operandsEqu (left, result)) {
11032                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11033                 goto release;
11034         }
11035 #endif
11036
11037 #if 0
11038         /* if they are the same registers */
11039         if (pic16_sameRegs(AOP(left),AOP(result))) {
11040                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11041                 goto release;
11042         }
11043 #endif
11044
11045 #if 1
11046         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11047                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11048                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11049                 goto release;
11050         }
11051 #endif
11052
11053
11054 #if 0
11055         if ( AOP_TYPE(left) == AOP_PCODE) {
11056                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11057                                 AOP(left)->aopu.pcop->name,
11058                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11059                                 PCOR(AOP(left)->aopu.pcop)->instance:
11060                                 PCOI(AOP(left)->aopu.pcop)->offset);
11061         }
11062 #endif
11063
11064         if(AOP(left)->aopu.pcop->type == PO_DIR)
11065                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11066
11067         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11068
11069         while (size--) {
11070                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11071                 
11072                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11073                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11074                         pic16_mov2w(AOP(left), offset); // patch 8
11075                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11076                 } else {
11077                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11078                                 pic16_popGet(AOP(left), offset), //patch 8
11079                                 pic16_popGet(AOP(result), offset)));
11080                 }
11081
11082                 offset++;
11083                 leoffset++;
11084         }
11085
11086 release:
11087     pic16_freeAsmop(result,NULL,ic,TRUE);
11088 }
11089
11090
11091
11092 /*-----------------------------------------------------------------*/
11093 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11094 /*-----------------------------------------------------------------*/
11095 static void genNearPointerGet (operand *left, 
11096                                operand *result, 
11097                                iCode *ic)
11098 {
11099   asmop *aop = NULL;
11100   //regs *preg = NULL ;
11101   sym_link *rtype, *retype;
11102   sym_link *ltype = operandType(left);    
11103
11104     FENTRY;
11105     
11106     rtype = operandType(result);
11107     retype= getSpec(rtype);
11108     
11109     pic16_aopOp(left,ic,FALSE);
11110
11111 //    pic16_DumpOp("(left)",left);
11112 //    pic16_DumpOp("(result)",result);
11113
11114     /* if left is rematerialisable and
11115      * result is not bit variable type and
11116      * the left is pointer to data space i.e
11117      * lower 128 bytes of space */
11118     
11119     if (AOP_TYPE(left) == AOP_PCODE
11120       && !IS_BITFIELD(retype)
11121       && DCL_TYPE(ltype) == POINTER) {
11122
11123         genDataPointerGet (left,result,ic);
11124         pic16_freeAsmop(left, NULL, ic, TRUE);
11125         return ;
11126     }
11127     
11128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11129     pic16_aopOp (result,ic,FALSE);
11130     
11131     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11132
11133 #if 1
11134     if(IS_BITFIELD( retype )
11135       && (SPEC_BLEN(operandType(result))==1)
11136     ) {
11137       iCode *nextic;
11138       pCodeOp *jop;
11139       int bitstrt, bytestrt;
11140
11141         /* if this is bitfield of size 1, see if we are checking the value
11142          * of a single bit in an if-statement,
11143          * if yes, then don't generate usual code, but execute the
11144          * genIfx directly -- VR */
11145
11146         nextic = ic->next;
11147
11148         /* CHECK: if next iCode is IFX
11149          * and current result operand is nextic's conditional operand
11150          * and current result operand live ranges ends at nextic's key number
11151          */
11152         if((nextic->op == IFX)
11153           && (result == IC_COND(nextic))
11154           && (OP_LIVETO(result) == nextic->seq)
11155           ) {
11156             /* everything is ok then */
11157             /* find a way to optimize the genIfx iCode */
11158
11159             bytestrt = SPEC_BSTR(operandType(result))/8;
11160             bitstrt = SPEC_BSTR(operandType(result))%8;
11161             
11162             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11163
11164             genIfxpCOpJump(nextic, jop);
11165             
11166             pic16_freeAsmop(left, NULL, ic, TRUE);
11167             pic16_freeAsmop(result, NULL, ic, TRUE);
11168             return;
11169         }
11170     }
11171 #endif
11172
11173
11174     /* if the value is already in a pointer register
11175      * then don't need anything more */
11176     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11177       /* otherwise get a free pointer register */
11178       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11179                 
11180       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11181       /* bitfields will be handled by genUnpackBits */
11182       if(!IS_BITFIELD(retype)) {
11183
11184         if(is_LitAOp( AOP(left) )) {
11185           pic16_loadFSR0( left );
11186         } else {
11187             // set up FSR0 with address from left
11188             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11189             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11190         }
11191       }
11192     }
11193
11194     /* if bitfield then unpack the bits */
11195     if (IS_BITFIELD(retype)) 
11196       genUnpackBits (result, left, NULL, POINTER);
11197     else {
11198       /* we have can just get the values */
11199       int size = AOP_SIZE(result);
11200       int offset = 0;   
11201         
11202       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11203
11204       /* fsr0 is loaded already -- VR */
11205 //      pic16_loadFSR0( left );
11206
11207 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11208 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11209       while(size--) {
11210         if(size) {
11211           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11212                 pic16_popGet(AOP(result), offset++)));
11213         } else {
11214           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11215                 pic16_popGet(AOP(result), offset++)));
11216         }
11217       }
11218 #if 0
11219 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11220 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11221       if(size)
11222         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11223 #endif
11224 /*
11225         while (size--) {
11226             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11227
11228                 pic16_emitcode("mov","a,@%s",rname);
11229                 pic16_aopPut(AOP(result),"a",offset);
11230             } else {
11231                 sprintf(buffer,"@%s",rname);
11232                 pic16_aopPut(AOP(result),buffer,offset);
11233             }
11234             offset++ ;
11235             if (size)
11236                 pic16_emitcode("inc","%s",rname);
11237         }
11238 */
11239     }
11240
11241     /* now some housekeeping stuff */
11242     if (aop) {
11243       /* we had to allocate for this iCode */
11244       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11245       pic16_freeAsmop(NULL,aop,ic,TRUE);
11246     } else { 
11247       /* we did not allocate which means left
11248        * already in a pointer register, then
11249        * if size > 0 && this could be used again
11250        * we have to point it back to where it 
11251        * belongs */
11252       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11253       if (AOP_SIZE(result) > 1
11254         && !OP_SYMBOL(left)->remat
11255         && ( OP_SYMBOL(left)->liveTo > ic->seq
11256             || ic->depth )) {
11257 //        int size = AOP_SIZE(result) - 1;
11258 //        while (size--)
11259 //          pic16_emitcode("dec","%s",rname);
11260         }
11261     }
11262
11263     /* done */
11264     pic16_freeAsmop(left,NULL,ic,TRUE);
11265     pic16_freeAsmop(result,NULL,ic,TRUE);
11266 }
11267
11268 /*-----------------------------------------------------------------*/
11269 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11270 /*-----------------------------------------------------------------*/
11271 static void genPagedPointerGet (operand *left, 
11272                                operand *result, 
11273                                iCode *ic)
11274 {
11275     asmop *aop = NULL;
11276     regs *preg = NULL ;
11277     char *rname ;
11278     sym_link *rtype, *retype;    
11279
11280     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11281
11282     rtype = operandType(result);
11283     retype= getSpec(rtype);
11284     
11285     pic16_aopOp(left,ic,FALSE);
11286
11287   /* if the value is already in a pointer register
11288        then don't need anything more */
11289     if (!AOP_INPREG(AOP(left))) {
11290         /* otherwise get a free pointer register */
11291         aop = newAsmop(0);
11292         preg = getFreePtr(ic,&aop,FALSE);
11293         pic16_emitcode("mov","%s,%s",
11294                 preg->name,
11295                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11296         rname = preg->name ;
11297     } else
11298         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11299     
11300     pic16_freeAsmop(left,NULL,ic,TRUE);
11301     pic16_aopOp (result,ic,FALSE);
11302
11303     /* if bitfield then unpack the bits */
11304     if (IS_BITFIELD(retype)) 
11305         genUnpackBits (result,left,rname,PPOINTER);
11306     else {
11307         /* we have can just get the values */
11308         int size = AOP_SIZE(result);
11309         int offset = 0 ;        
11310         
11311         while (size--) {
11312             
11313             pic16_emitcode("movx","a,@%s",rname);
11314             pic16_aopPut(AOP(result),"a",offset);
11315             
11316             offset++ ;
11317             
11318             if (size)
11319                 pic16_emitcode("inc","%s",rname);
11320         }
11321     }
11322
11323     /* now some housekeeping stuff */
11324     if (aop) {
11325         /* we had to allocate for this iCode */
11326         pic16_freeAsmop(NULL,aop,ic,TRUE);
11327     } else { 
11328         /* we did not allocate which means left
11329            already in a pointer register, then
11330            if size > 0 && this could be used again
11331            we have to point it back to where it 
11332            belongs */
11333         if (AOP_SIZE(result) > 1 &&
11334             !OP_SYMBOL(left)->remat &&
11335             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11336               ic->depth )) {
11337             int size = AOP_SIZE(result) - 1;
11338             while (size--)
11339                 pic16_emitcode("dec","%s",rname);
11340         }
11341     }
11342
11343     /* done */
11344     pic16_freeAsmop(result,NULL,ic,TRUE);
11345     
11346         
11347 }
11348
11349 /*-----------------------------------------------------------------*/
11350 /* genFarPointerGet - gget value from far space                    */
11351 /*-----------------------------------------------------------------*/
11352 static void genFarPointerGet (operand *left,
11353                               operand *result, iCode *ic)
11354 {
11355     int size, offset ;
11356     sym_link *retype = getSpec(operandType(result));
11357
11358     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11359
11360     pic16_aopOp(left,ic,FALSE);
11361
11362     /* if the operand is already in dptr 
11363     then we do nothing else we move the value to dptr */
11364     if (AOP_TYPE(left) != AOP_STR) {
11365         /* if this is remateriazable */
11366         if (AOP_TYPE(left) == AOP_IMMD)
11367             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11368         else { /* we need to get it byte by byte */
11369             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11370             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11371             if (options.model == MODEL_FLAT24)
11372             {
11373                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11374             }
11375         }
11376     }
11377     /* so dptr know contains the address */
11378     pic16_freeAsmop(left,NULL,ic,TRUE);
11379     pic16_aopOp(result,ic,FALSE);
11380
11381     /* if bit then unpack */
11382     if (IS_BITFIELD(retype)) 
11383         genUnpackBits(result,left,"dptr",FPOINTER);
11384     else {
11385         size = AOP_SIZE(result);
11386         offset = 0 ;
11387
11388         while (size--) {
11389             pic16_emitcode("movx","a,@dptr");
11390             pic16_aopPut(AOP(result),"a",offset++);
11391             if (size)
11392                 pic16_emitcode("inc","dptr");
11393         }
11394     }
11395
11396     pic16_freeAsmop(result,NULL,ic,TRUE);
11397 }
11398
11399 #if 0
11400 /*-----------------------------------------------------------------*/
11401 /* genCodePointerGet - get value from code space                  */
11402 /*-----------------------------------------------------------------*/
11403 static void genCodePointerGet (operand *left,
11404                                 operand *result, iCode *ic)
11405 {
11406     int size, offset ;
11407     sym_link *retype = getSpec(operandType(result));
11408
11409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11410
11411     pic16_aopOp(left,ic,FALSE);
11412
11413     /* if the operand is already in dptr 
11414     then we do nothing else we move the value to dptr */
11415     if (AOP_TYPE(left) != AOP_STR) {
11416         /* if this is remateriazable */
11417         if (AOP_TYPE(left) == AOP_IMMD)
11418             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11419         else { /* we need to get it byte by byte */
11420             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11421             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11422             if (options.model == MODEL_FLAT24)
11423             {
11424                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11425             }
11426         }
11427     }
11428     /* so dptr know contains the address */
11429     pic16_freeAsmop(left,NULL,ic,TRUE);
11430     pic16_aopOp(result,ic,FALSE);
11431
11432     /* if bit then unpack */
11433     if (IS_BITFIELD(retype)) 
11434         genUnpackBits(result,left,"dptr",CPOINTER);
11435     else {
11436         size = AOP_SIZE(result);
11437         offset = 0 ;
11438
11439         while (size--) {
11440             pic16_emitcode("clr","a");
11441             pic16_emitcode("movc","a,@a+dptr");
11442             pic16_aopPut(AOP(result),"a",offset++);
11443             if (size)
11444                 pic16_emitcode("inc","dptr");
11445         }
11446     }
11447
11448     pic16_freeAsmop(result,NULL,ic,TRUE);
11449 }
11450 #endif
11451
11452 #if 0
11453 /*-----------------------------------------------------------------*/
11454 /* genGenPointerGet - gget value from generic pointer space        */
11455 /*-----------------------------------------------------------------*/
11456 static void genGenPointerGet (operand *left,
11457                               operand *result, iCode *ic)
11458 {
11459   int size, offset, lit;
11460   sym_link *retype = getSpec(operandType(result));
11461
11462         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11463         pic16_aopOp(left,ic,FALSE);
11464         pic16_aopOp(result,ic,FALSE);
11465         size = AOP_SIZE(result);
11466
11467         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11468
11469         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11470
11471                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11472                 // load FSR0 from immediate
11473                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11474
11475 //              pic16_loadFSR0( left );
11476
11477                 offset = 0;
11478                 while(size--) {
11479                         if(size) {
11480                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11481                         } else {
11482                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11483                         }
11484                         offset++;
11485                 }
11486                 goto release;
11487
11488         }
11489         else { /* we need to get it byte by byte */
11490                 // set up FSR0 with address from left
11491                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11492                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11493
11494                 offset = 0 ;
11495
11496                 while(size--) {
11497                         if(size) {
11498                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11499                         } else {
11500                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11501                         }
11502                         offset++;
11503                 }
11504                 goto release;
11505         }
11506
11507   /* if bit then unpack */
11508         if (IS_BITFIELD(retype)) 
11509                 genUnpackBits(result,left,"BAD",GPOINTER);
11510
11511         release:
11512         pic16_freeAsmop(left,NULL,ic,TRUE);
11513         pic16_freeAsmop(result,NULL,ic,TRUE);
11514
11515 }
11516 #endif
11517
11518
11519 /*-----------------------------------------------------------------*/
11520 /* genGenPointerGet - gget value from generic pointer space        */
11521 /*-----------------------------------------------------------------*/
11522 static void genGenPointerGet (operand *left,
11523                               operand *result, iCode *ic)
11524 {
11525   int size, offset, lit;
11526   sym_link *retype = getSpec(operandType(result));
11527   char fgptrget[32];
11528
11529     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11530     pic16_aopOp(left,ic,FALSE);
11531     pic16_aopOp(result,ic,FALSE);
11532     size = AOP_SIZE(result);
11533
11534     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11535
11536     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11537
11538       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11539       // load FSR0 from immediate
11540       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11541
11542       werror(W_POSSBUG2, __FILE__, __LINE__);
11543
11544       offset = 0;
11545       while(size--) {
11546         if(size) {
11547           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11548         } else {
11549           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11550         }
11551         offset++;
11552       }
11553
11554       goto release;
11555
11556     } else { /* we need to get it byte by byte */
11557
11558       /* set up WREG:PRODL:FSR0L with address from left */
11559       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11560       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11561       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11562       
11563       switch( size ) {
11564         case 1: strcpy(fgptrget, "__gptrget1"); break;
11565         case 2: strcpy(fgptrget, "__gptrget2"); break;
11566         case 3: strcpy(fgptrget, "__gptrget3"); break;
11567         case 4: strcpy(fgptrget, "__gptrget4"); break;
11568         default:
11569           werror(W_POSSBUG2, __FILE__, __LINE__);
11570           abort();
11571       }
11572       
11573       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11574       
11575       assignResultValue(result, 1);
11576       
11577       {
11578         symbol *sym;
11579
11580           sym = newSymbol( fgptrget, 0 );
11581           strcpy(sym->rname, fgptrget);
11582           checkAddSym(&externs, sym);
11583
11584 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11585       }
11586               
11587       goto release;
11588     }
11589
11590   /* if bit then unpack */
11591     if (IS_BITFIELD(retype)) 
11592       genUnpackBits(result,left,"BAD",GPOINTER);
11593
11594 release:
11595   pic16_freeAsmop(left,NULL,ic,TRUE);
11596   pic16_freeAsmop(result,NULL,ic,TRUE);
11597 }
11598
11599 /*-----------------------------------------------------------------*/
11600 /* genConstPointerGet - get value from const generic pointer space */
11601 /*-----------------------------------------------------------------*/
11602 static void genConstPointerGet (operand *left,
11603                                 operand *result, iCode *ic)
11604 {
11605   //sym_link *retype = getSpec(operandType(result));
11606   // symbol *albl = newiTempLabel(NULL);        // patch 15
11607   // symbol *blbl = newiTempLabel(NULL);        //
11608   // PIC_OPCODE poc;                            // patch 15
11609   int size;
11610   int offset = 0;
11611
11612   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11613   pic16_aopOp(left,ic,FALSE);
11614   pic16_aopOp(result,ic,TRUE);
11615   size = AOP_SIZE(result);
11616
11617   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11618
11619   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11620
11621   // set up table pointer
11622   if( (AOP_TYPE(left) == AOP_PCODE) 
11623       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11624           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11625     {
11626       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11627       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11628       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11629       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11630       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11631       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11632   } else {
11633     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11634     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11635     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11636   }
11637
11638   while(size--) {
11639     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11640     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11641     offset++;
11642   }
11643     
11644   pic16_freeAsmop(left,NULL,ic,TRUE);
11645   pic16_freeAsmop(result,NULL,ic,TRUE);
11646 }
11647
11648
11649 /*-----------------------------------------------------------------*/
11650 /* genPointerGet - generate code for pointer get                   */
11651 /*-----------------------------------------------------------------*/
11652 static void genPointerGet (iCode *ic)
11653 {
11654   operand *left, *result ;
11655   sym_link *type, *etype;
11656   int p_type;
11657
11658     FENTRY;
11659     
11660     left = IC_LEFT(ic);
11661     result = IC_RESULT(ic) ;
11662
11663     /* depending on the type of pointer we need to
11664     move it to the correct pointer register */
11665     type = operandType(left);
11666     etype = getSpec(type);
11667
11668 #if 0
11669     if (IS_PTR_CONST(type))
11670 #else
11671     if (IS_CODEPTR(type))
11672 #endif
11673       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11674
11675     /* if left is of type of pointer then it is simple */
11676     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11677       p_type = DCL_TYPE(type);
11678     else {
11679       /* we have to go by the storage class */
11680       p_type = PTR_TYPE(SPEC_OCLS(etype));
11681
11682       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11683
11684       if (SPEC_OCLS(etype)->codesp ) {
11685         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11686         //p_type = CPOINTER ;   
11687       } else
11688       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11689         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11690         /*p_type = FPOINTER ;*/ 
11691       } else
11692       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11693         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11694         /* p_type = PPOINTER; */
11695       } else
11696       if (SPEC_OCLS(etype) == idata ) {
11697         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11698         /* p_type = IPOINTER; */
11699       } else {
11700         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11701         /* p_type = POINTER ; */
11702       }
11703     }
11704
11705     /* now that we have the pointer type we assign
11706     the pointer values */
11707     switch (p_type) {
11708       case POINTER:     
11709       case IPOINTER:
11710         genNearPointerGet (left,result,ic);
11711         break;
11712
11713       case PPOINTER:
11714         genPagedPointerGet(left,result,ic);
11715         break;
11716
11717       case FPOINTER:
11718         genFarPointerGet (left,result,ic);
11719         break;
11720
11721       case CPOINTER:
11722         genConstPointerGet (left,result,ic);
11723         //pic16_emitcodePointerGet (left,result,ic);
11724         break;
11725
11726       case GPOINTER:
11727 #if 0
11728       if (IS_PTR_CONST(type))
11729         genConstPointerGet (left,result,ic);
11730       else
11731 #endif
11732         genGenPointerGet (left,result,ic);
11733       break;
11734
11735     default:
11736       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11737               "genPointerGet: illegal pointer type");
11738     
11739     }
11740 }
11741
11742 /*-----------------------------------------------------------------*/
11743 /* genPackBits - generates code for packed bit storage             */
11744 /*-----------------------------------------------------------------*/
11745 static void genPackBits (sym_link    *etype , operand *result,
11746                          operand *right ,
11747                          char *rname, int p_type)
11748 {
11749   int shCnt = 0 ;
11750   int offset = 0  ;
11751   int rLen = 0 ;
11752   int blen, bstr ;   
11753   sym_link *retype;
11754   char *l ;
11755
11756         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11757         blen = SPEC_BLEN(etype);
11758         bstr = SPEC_BSTR(etype);
11759
11760         retype = getSpec(operandType(right));
11761
11762         if(AOP_TYPE(right) == AOP_LIT) {
11763                 if((blen == 1) && (bstr < 8)) {
11764                   unsigned long lit;
11765                         /* it is a single bit, so use the appropriate bit instructions */
11766
11767                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11768
11769                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11770 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11771                         if((p_type == POINTER) && (result)) {
11772                                 /* workaround to reduce the extra lfsr instruction */
11773                                 if(lit) {
11774                                         pic16_emitpcode(POC_BSF,
11775                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11776                                 } else {
11777                                         pic16_emitpcode(POC_BCF,
11778                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11779                                 }
11780                         } else {
11781                                 pic16_loadFSR0( result );
11782                                 if(lit) {
11783                                         pic16_emitpcode(POC_BSF,
11784                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11785                                 } else {
11786                                         pic16_emitpcode(POC_BCF,
11787                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11788                                 }
11789                         }
11790         
11791                   return;
11792                 }
11793
11794                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11795                 offset++;
11796         } else
11797         if(IS_BITFIELD(retype) 
11798           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11799           && (blen == 1)) {
11800           int rblen, rbstr;
11801
11802             rblen = SPEC_BLEN( retype );
11803             rbstr = SPEC_BSTR( retype );
11804             
11805
11806             if(IS_BITFIELD(etype)) {
11807               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11808               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11809             } else {
11810               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11811             }
11812             
11813             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11814             
11815             if(IS_BITFIELD(etype)) {
11816               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11817             } else {
11818               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11819             }
11820
11821             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11822             
11823             return;
11824         } else
11825           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11826
11827         /* if the bit length is less than or   */
11828         /* it exactly fits a byte then         */
11829         if((shCnt=SPEC_BSTR(etype))
11830                 || SPEC_BLEN(etype) <= 8 )  {
11831                 int fsr0_setup = 0;
11832
11833                 if (blen != 8 || bstr != 0) {
11834                   // we need to combine the value with the old value
11835                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11836
11837                   /* shift left acc */
11838                   AccLsh(shCnt);
11839
11840                   /* using PRODH as a temporary register here */
11841                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11842
11843                   /* get old value */
11844                   switch (p_type) {
11845                         case FPOINTER:
11846                         case POINTER:
11847                                 pic16_loadFSR0( result );
11848                                 fsr0_setup = 1;
11849                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11850 //                              pic16_emitcode ("mov","b,a");
11851 //                              pic16_emitcode("mov","a,@%s",rname);
11852                                 break;
11853
11854                         case GPOINTER:
11855                                 if (AOP(result)->aopu.aop_reg[2]) {
11856                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11857                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11858                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11859                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11860                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11861                                   {
11862                                     symbol *sym;
11863                                     sym = newSymbol( "__gptrget1", 0 );
11864                                     strcpy(sym->rname, "__gptrget1");
11865                                     checkAddSym(&externs, sym);
11866                                   }
11867                                 } else {
11868                                   // data pointer (just 2 byte given)
11869                                   pic16_loadFSR0( result );
11870                                   fsr0_setup = 1;
11871                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11872                                 }
11873                                 
11874                                 // warnings will be emitted below
11875                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11876                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11877                                 break;
11878
11879                         default:
11880                                 assert (0 && "invalid pointer type specified");
11881                                 break;
11882                   }
11883 #if 1
11884                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11885                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11886                                         (unsigned char)(0xff >> (8-bstr))) ));
11887                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11888                 } // if (blen != 8 || bstr != 0)
11889
11890                 /* write new value back */
11891                 switch (p_type) {
11892                         case FPOINTER:
11893                         case POINTER:
11894                                 if (!fsr0_setup) pic16_loadFSR0( result );
11895                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11896                                 break;
11897
11898                         case GPOINTER:
11899                                 if (AOP(result)->aopu.aop_reg[2]) {
11900                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11901                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11902                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11903                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11904                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11905                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11906                                   {
11907                                     symbol *sym;
11908                                     sym = newSymbol( "__gptrput1", 0 );
11909                                     strcpy(sym->rname, "__gptrput1");
11910                                     checkAddSym(&externs, sym);
11911                                   }
11912                                 } else {
11913                                   // data pointer (just 2 byte given)
11914                                   if (!fsr0_setup) pic16_loadFSR0( result );
11915                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11916                                 }
11917                                 
11918                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11919                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11920                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11921                                 break;
11922
11923                         default:
11924                                 assert (0 && "invalid pointer type specified");
11925                                 break;
11926                 }
11927 #endif
11928
11929           return;
11930         }
11931
11932
11933         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11934         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11935         exit(-1);
11936
11937
11938     /* if we r done */
11939     if ( SPEC_BLEN(etype) <= 8 )
11940         return ;
11941
11942     pic16_emitcode("inc","%s",rname);
11943     rLen = SPEC_BLEN(etype) ;     
11944
11945
11946
11947     /* now generate for lengths greater than one byte */
11948     while (1) {
11949
11950         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11951
11952         rLen -= 8 ;
11953         if (rLen <= 0 )
11954             break ;
11955
11956         switch (p_type) {
11957             case POINTER:
11958                 if (*l == '@') {
11959                     MOVA(l);
11960                     pic16_emitcode("mov","@%s,a",rname);
11961                 } else
11962                     pic16_emitcode("mov","@%s,%s",rname,l);
11963                 break;
11964
11965             case FPOINTER:
11966                 MOVA(l);
11967                 pic16_emitcode("movx","@dptr,a");
11968                 break;
11969
11970             case GPOINTER:
11971                 MOVA(l);
11972                 DEBUGpic16_emitcode(";lcall","__gptrput");
11973                 break;  
11974         }   
11975         pic16_emitcode ("inc","%s",rname);
11976     }
11977
11978     MOVA(l);
11979
11980     /* last last was not complete */
11981     if (rLen)   {
11982         /* save the byte & read byte */
11983         switch (p_type) {
11984             case POINTER:
11985                 pic16_emitcode ("mov","b,a");
11986                 pic16_emitcode("mov","a,@%s",rname);
11987                 break;
11988
11989             case FPOINTER:
11990                 pic16_emitcode ("mov","b,a");
11991                 pic16_emitcode("movx","a,@dptr");
11992                 break;
11993
11994             case GPOINTER:
11995                 pic16_emitcode ("push","b");
11996                 pic16_emitcode ("push","acc");
11997                 pic16_emitcode ("lcall","__gptrget");
11998                 pic16_emitcode ("pop","b");
11999                 break;
12000         }
12001
12002         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
12003         pic16_emitcode ("orl","a,b");
12004     }
12005
12006     if (p_type == GPOINTER)
12007         pic16_emitcode("pop","b");
12008
12009     switch (p_type) {
12010
12011     case POINTER:
12012         pic16_emitcode("mov","@%s,a",rname);
12013         break;
12014         
12015     case FPOINTER:
12016         pic16_emitcode("movx","@dptr,a");
12017         break;
12018         
12019     case GPOINTER:
12020         DEBUGpic16_emitcode(";lcall","__gptrput");
12021         break;                  
12022     }
12023 }
12024 /*-----------------------------------------------------------------*/
12025 /* genDataPointerSet - remat pointer to data space                 */
12026 /*-----------------------------------------------------------------*/
12027 static void genDataPointerSet(operand *right,
12028                               operand *result,
12029                               iCode *ic)
12030 {
12031     int size, offset = 0, resoffset=0 ;
12032
12033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12034     pic16_aopOp(right,ic,FALSE);
12035
12036     size = AOP_SIZE(right);
12037
12038 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12039
12040 #if 0
12041     if ( AOP_TYPE(result) == AOP_PCODE) {
12042       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12043               AOP(result)->aopu.pcop->name,
12044                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12045               PCOR(AOP(result)->aopu.pcop)->instance:
12046               PCOI(AOP(result)->aopu.pcop)->offset);
12047     }
12048 #endif
12049
12050         if(AOP(result)->aopu.pcop->type == PO_DIR)
12051                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12052
12053         while (size--) {
12054                 if (AOP_TYPE(right) == AOP_LIT) {
12055                   unsigned int lit;
12056
12057                     if(!IS_FLOAT(operandType( right )))
12058                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12059                     else {
12060                       union {
12061                         unsigned long lit_int;
12062                         float lit_float;
12063                       } info;
12064         
12065                         /* take care if literal is a float */
12066                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12067                         lit = info.lit_int;
12068                     }
12069
12070                     lit = lit >> (8*offset);
12071                     if(lit&0xff) {
12072                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12073                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12074                     } else {
12075                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12076                     }
12077                 } else {
12078                   pic16_mov2w(AOP(right), offset);
12079                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12080                 }
12081                 offset++;
12082                 resoffset++;
12083         }
12084
12085     pic16_freeAsmop(right,NULL,ic,TRUE);
12086 }
12087
12088
12089
12090 /*-----------------------------------------------------------------*/
12091 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12092 /*-----------------------------------------------------------------*/
12093 static void genNearPointerSet (operand *right,
12094                                operand *result, 
12095                                iCode *ic)
12096 {
12097   asmop *aop = NULL;
12098   char *l;
12099   sym_link *retype;
12100   sym_link *ptype = operandType(result);
12101   sym_link *resetype;
12102     
12103         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12104         retype= getSpec(operandType(right));
12105         resetype = getSpec(operandType(result));
12106   
12107         pic16_aopOp(result,ic,FALSE);
12108     
12109         /* if the result is rematerializable &
12110          * in data space & not a bit variable */
12111         
12112         /* and result is not a bit variable */
12113         if (AOP_TYPE(result) == AOP_PCODE
12114 //              && AOP_TYPE(result) == AOP_IMMD
12115                 && DCL_TYPE(ptype) == POINTER
12116                 && !IS_BITFIELD(retype)
12117                 && !IS_BITFIELD(resetype)) {
12118
12119                 genDataPointerSet (right,result,ic);
12120                 pic16_freeAsmop(result,NULL,ic,TRUE);
12121           return;
12122         }
12123
12124         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12125         pic16_aopOp(right,ic,FALSE);
12126         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12127
12128         /* if the value is already in a pointer register
12129          * then don't need anything more */
12130         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12131                 /* otherwise get a free pointer register */
12132                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12133
12134 //              if( (AOP_TYPE(result) == AOP_PCODE) 
12135 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12136 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12137                 if(is_LitAOp( AOP(result) ))
12138                 {
12139                   if(!IS_BITFIELD(resetype))
12140                         pic16_loadFSR0( result );  // patch 10
12141                 } else {
12142                   if(!IS_BITFIELD(resetype)) {
12143                         // set up FSR0 with address of result
12144                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12145                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12146                   }
12147                 }
12148
12149         }
12150 //      else
12151 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12152
12153         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12154
12155 //      pic16_loadFSR0( result );
12156
12157         /* if bitfield then unpack the bits */
12158         if (IS_BITFIELD(resetype)) {
12159                 genPackBits (resetype, result, right, NULL, POINTER);
12160         } else {
12161                 /* we have can just get the values */
12162           int size = AOP_SIZE(right);
12163           int offset = 0 ;    
12164
12165                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12166                 while (size--) {
12167                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12168                         if (*l == '@' ) {
12169                                 //MOVA(l);
12170                                 //pic16_emitcode("mov","@%s,a",rname);
12171                                 pic16_emitcode("movf","indf0,w ;1");
12172                         } else {
12173
12174                                 if (AOP_TYPE(right) == AOP_LIT) {
12175                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12176                                         if (size) {
12177                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12178                                         } else {
12179                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12180                                         }
12181                                 } else { // no literal
12182                                         if(size) {
12183                                                 pic16_emitpcode(POC_MOVFF,
12184                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12185                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12186                                         } else {
12187                                                 pic16_emitpcode(POC_MOVFF,
12188                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12189                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12190                                         }
12191                                 }
12192                         }
12193                         offset++;
12194                 }
12195         }
12196
12197         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12198         /* now some housekeeping stuff */
12199         if (aop) {
12200                 /* we had to allocate for this iCode */
12201                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12202         } else { 
12203                 /* we did not allocate which means left
12204                  * already in a pointer register, then
12205                  * if size > 0 && this could be used again
12206                  * we have to point it back to where it 
12207                  * belongs */
12208                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12209                 if (AOP_SIZE(right) > 1
12210                         && !OP_SYMBOL(result)->remat
12211                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12212                                 || ic->depth )) {
12213
12214                   int size = AOP_SIZE(right) - 1;
12215
12216                         while (size--)
12217                                 pic16_emitcode("decf","fsr0,f");
12218                         //pic16_emitcode("dec","%s",rname);
12219                 }
12220         }
12221
12222         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12223         /* done */
12224 //release:
12225         pic16_freeAsmop(right,NULL,ic,TRUE);
12226         pic16_freeAsmop(result,NULL,ic,TRUE);
12227 }
12228
12229 /*-----------------------------------------------------------------*/
12230 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12231 /*-----------------------------------------------------------------*/
12232 static void genPagedPointerSet (operand *right,
12233                                operand *result, 
12234                                iCode *ic)
12235 {
12236     asmop *aop = NULL;
12237     regs *preg = NULL ;
12238     char *rname , *l;
12239     sym_link *retype;
12240        
12241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12242
12243     retype= getSpec(operandType(right));
12244     
12245     pic16_aopOp(result,ic,FALSE);
12246     
12247     /* if the value is already in a pointer register
12248        then don't need anything more */
12249     if (!AOP_INPREG(AOP(result))) {
12250         /* otherwise get a free pointer register */
12251         aop = newAsmop(0);
12252         preg = getFreePtr(ic,&aop,FALSE);
12253         pic16_emitcode("mov","%s,%s",
12254                 preg->name,
12255                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12256         rname = preg->name ;
12257     } else
12258         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12259     
12260     pic16_freeAsmop(result,NULL,ic,TRUE);
12261     pic16_aopOp (right,ic,FALSE);
12262
12263     /* if bitfield then unpack the bits */
12264     if (IS_BITFIELD(retype)) 
12265         genPackBits (retype,result,right,rname,PPOINTER);
12266     else {
12267         /* we have can just get the values */
12268         int size = AOP_SIZE(right);
12269         int offset = 0 ;        
12270         
12271         while (size--) {
12272             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12273             
12274             MOVA(l);
12275             pic16_emitcode("movx","@%s,a",rname);
12276
12277             if (size)
12278                 pic16_emitcode("inc","%s",rname);
12279
12280             offset++;
12281         }
12282     }
12283     
12284     /* now some housekeeping stuff */
12285     if (aop) {
12286         /* we had to allocate for this iCode */
12287         pic16_freeAsmop(NULL,aop,ic,TRUE);
12288     } else { 
12289         /* we did not allocate which means left
12290            already in a pointer register, then
12291            if size > 0 && this could be used again
12292            we have to point it back to where it 
12293            belongs */
12294         if (AOP_SIZE(right) > 1 &&
12295             !OP_SYMBOL(result)->remat &&
12296             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12297               ic->depth )) {
12298             int size = AOP_SIZE(right) - 1;
12299             while (size--)
12300                 pic16_emitcode("dec","%s",rname);
12301         }
12302     }
12303
12304     /* done */
12305     pic16_freeAsmop(right,NULL,ic,TRUE);
12306     
12307         
12308 }
12309
12310 /*-----------------------------------------------------------------*/
12311 /* genFarPointerSet - set value from far space                     */
12312 /*-----------------------------------------------------------------*/
12313 static void genFarPointerSet (operand *right,
12314                               operand *result, iCode *ic)
12315 {
12316     int size, offset ;
12317     sym_link *retype = getSpec(operandType(right));
12318
12319     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12320     pic16_aopOp(result,ic,FALSE);
12321
12322     /* if the operand is already in dptr 
12323     then we do nothing else we move the value to dptr */
12324     if (AOP_TYPE(result) != AOP_STR) {
12325         /* if this is remateriazable */
12326         if (AOP_TYPE(result) == AOP_IMMD)
12327             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12328         else { /* we need to get it byte by byte */
12329             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12330             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12331             if (options.model == MODEL_FLAT24)
12332             {
12333                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12334             }
12335         }
12336     }
12337     /* so dptr know contains the address */
12338     pic16_freeAsmop(result,NULL,ic,TRUE);
12339     pic16_aopOp(right,ic,FALSE);
12340
12341     /* if bit then unpack */
12342     if (IS_BITFIELD(retype)) 
12343         genPackBits(retype,result,right,"dptr",FPOINTER);
12344     else {
12345         size = AOP_SIZE(right);
12346         offset = 0 ;
12347
12348         while (size--) {
12349             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12350             MOVA(l);
12351             pic16_emitcode("movx","@dptr,a");
12352             if (size)
12353                 pic16_emitcode("inc","dptr");
12354         }
12355     }
12356
12357     pic16_freeAsmop(right,NULL,ic,TRUE);
12358 }
12359
12360 /*-----------------------------------------------------------------*/
12361 /* genGenPointerSet - set value from generic pointer space         */
12362 /*-----------------------------------------------------------------*/
12363 #if 0
12364 static void genGenPointerSet (operand *right,
12365                               operand *result, iCode *ic)
12366 {
12367         int i, size, offset, lit;
12368         sym_link *retype = getSpec(operandType(right));
12369
12370         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12371
12372         pic16_aopOp(result,ic,FALSE);
12373         pic16_aopOp(right,ic,FALSE);
12374         size = AOP_SIZE(right);
12375         offset = 0;
12376
12377         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12378
12379         /* if the operand is already in dptr 
12380                 then we do nothing else we move the value to dptr */
12381         if (AOP_TYPE(result) != AOP_STR) {
12382                 /* if this is remateriazable */
12383                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12384                 // WARNING: anythig until "else" is untested!
12385                 if (AOP_TYPE(result) == AOP_IMMD) {
12386                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12387                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12388                         // load FSR0 from immediate
12389                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12390                         offset = 0;
12391                         while(size--) {
12392                                 if(size) {
12393                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12394                                 } else {
12395                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12396                                 }
12397                                 offset++;
12398                         }
12399                         goto release;
12400                 }
12401                 else { /* we need to get it byte by byte */
12402                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12403                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12404
12405                         // set up FSR0 with address of result
12406                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12407                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12408
12409                         /* hack hack! see if this the FSR. If so don't load W */
12410                         if(AOP_TYPE(right) != AOP_ACC) {
12411
12412                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12413
12414                                 if(AOP_TYPE(right) == AOP_LIT)
12415                                 {
12416                                         // copy literal
12417                                         // note: pic16_popGet handles sign extension
12418                                         for(i=0;i<size;i++) {
12419                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12420                                                 if(i < size-1)
12421                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12422                                                 else
12423                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12424                                         }
12425                                 } else {
12426                                         // copy regs
12427
12428                                         for(i=0;i<size;i++) {
12429                                                 if(i < size-1)
12430                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12431                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12432                                                 else
12433                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12434                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12435                                         }
12436                                 }
12437                                 goto release;
12438                         } 
12439                         // right = ACC
12440                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12441                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12442                         goto release;
12443         } // if (AOP_TYPE(result) != AOP_IMMD)
12444
12445         } // if (AOP_TYPE(result) != AOP_STR)
12446         /* so dptr know contains the address */
12447
12448
12449         /* if bit then unpack */
12450         if (IS_BITFIELD(retype)) 
12451                 genPackBits(retype,result,right,"dptr",GPOINTER);
12452         else {
12453                 size = AOP_SIZE(right);
12454                 offset = 0 ;
12455
12456                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12457
12458                 // set up FSR0 with address of result
12459                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12460                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12461         
12462                 while (size--) {
12463                         if (AOP_TYPE(right) == AOP_LIT) {
12464                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12465                                 if (size) {
12466                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12467                                 } else {
12468                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12469                                 }
12470                         } else { // no literal
12471                                 if(size) {
12472                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12473                                 } else {
12474                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12475                                 }
12476                         }
12477                         offset++;
12478                 }
12479         }
12480
12481         release:
12482         pic16_freeAsmop(right,NULL,ic,TRUE);
12483         pic16_freeAsmop(result,NULL,ic,TRUE);
12484 }
12485 #endif
12486
12487 static void genGenPointerSet (operand *right,
12488                               operand *result, iCode *ic)
12489 {
12490   int size;
12491   sym_link *retype = getSpec(operandType(right));
12492   char fgptrput[32];
12493
12494     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12495
12496     pic16_aopOp(result,ic,FALSE);
12497     pic16_aopOp(right,ic,FALSE);
12498     size = AOP_SIZE(right);
12499
12500     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12501
12502
12503     /* if bit then unpack */
12504     if (IS_BITFIELD(retype)) {
12505 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12506       genPackBits(retype,result,right,"dptr",GPOINTER);
12507       goto release;
12508     }
12509
12510     size = AOP_SIZE(right);
12511
12512     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12513
12514
12515
12516     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12517
12518     /* value of right+0 is placed on stack, which will be retrieved
12519      * by the support function this restoring the stack. The important
12520      * thing is that there is no need to manually restore stack pointer
12521      * here */
12522     pushaop(AOP(right), 0);
12523 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12524     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12525     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12526     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12527     
12528     /* load address to write to in WREG:FSR0H:FSR0L */
12529     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12530                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12531     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12532                                 pic16_popCopyReg(&pic16_pc_prodl)));
12533     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12534     
12535
12536     /* put code here */
12537     switch (size) {
12538       case 1: strcpy(fgptrput, "__gptrput1"); break;
12539       case 2: strcpy(fgptrput, "__gptrput2"); break;
12540       case 3: strcpy(fgptrput, "__gptrput3"); break;
12541       case 4: strcpy(fgptrput, "__gptrput4"); break;
12542       default:
12543         werror(W_POSSBUG2, __FILE__, __LINE__);
12544         abort();
12545     }
12546     
12547     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12548     
12549     {
12550       symbol *sym;
12551                   
12552         sym = newSymbol( fgptrput, 0 );
12553         strcpy(sym->rname, fgptrput);
12554         checkAddSym(&externs, sym);
12555     }
12556
12557 release:
12558     pic16_freeAsmop(right,NULL,ic,TRUE);
12559     pic16_freeAsmop(result,NULL,ic,TRUE);
12560 }
12561
12562 /*-----------------------------------------------------------------*/
12563 /* genPointerSet - stores the value into a pointer location        */
12564 /*-----------------------------------------------------------------*/
12565 static void genPointerSet (iCode *ic)
12566 {    
12567   operand *right, *result ;
12568   sym_link *type, *etype;
12569   int p_type;
12570
12571     FENTRY;
12572
12573     right = IC_RIGHT(ic);
12574     result = IC_RESULT(ic) ;
12575
12576     /* depending on the type of pointer we need to
12577     move it to the correct pointer register */
12578     type = operandType(result);
12579     etype = getSpec(type);
12580     /* if left is of type of pointer then it is simple */
12581     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12582         p_type = DCL_TYPE(type);
12583     }
12584     else {
12585         /* we have to go by the storage class */
12586         p_type = PTR_TYPE(SPEC_OCLS(etype));
12587
12588 /*      if (SPEC_OCLS(etype)->codesp ) { */
12589 /*          p_type = CPOINTER ;  */
12590 /*      } */
12591 /*      else */
12592 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12593 /*              p_type = FPOINTER ; */
12594 /*          else */
12595 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12596 /*                  p_type = PPOINTER ; */
12597 /*              else */
12598 /*                  if (SPEC_OCLS(etype) == idata ) */
12599 /*                      p_type = IPOINTER ; */
12600 /*                  else */
12601 /*                      p_type = POINTER ; */
12602     }
12603
12604     /* now that we have the pointer type we assign
12605     the pointer values */
12606     switch (p_type) {
12607       case POINTER:
12608       case IPOINTER:
12609         genNearPointerSet (right,result,ic);
12610         break;
12611
12612       case PPOINTER:
12613         genPagedPointerSet (right,result,ic);
12614         break;
12615
12616       case FPOINTER:
12617         genFarPointerSet (right,result,ic);
12618         break;
12619         
12620       case GPOINTER:
12621         genGenPointerSet (right,result,ic);
12622         break;
12623
12624       default:
12625         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12626           "genPointerSet: illegal pointer type");
12627     }
12628 }
12629
12630 /*-----------------------------------------------------------------*/
12631 /* genIfx - generate code for Ifx statement                        */
12632 /*-----------------------------------------------------------------*/
12633 static void genIfx (iCode *ic, iCode *popIc)
12634 {
12635   operand *cond = IC_COND(ic);
12636   int isbit =0;
12637
12638     FENTRY;
12639
12640     pic16_aopOp(cond,ic,FALSE);
12641
12642     /* get the value into acc */
12643     if (AOP_TYPE(cond) != AOP_CRY)
12644       pic16_toBoolean(cond);
12645     else
12646       isbit = 1;
12647     /* the result is now in the accumulator */
12648     pic16_freeAsmop(cond,NULL,ic,TRUE);
12649
12650     /* if there was something to be popped then do it */
12651     if (popIc)
12652       genIpop(popIc);
12653
12654     /* if the condition is  a bit variable */
12655     if (isbit && IS_ITEMP(cond) && 
12656         SPIL_LOC(cond)) {
12657       genIfxJump(ic,"c");
12658       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12659     } else {
12660       if (isbit && !IS_ITEMP(cond))
12661         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12662         else
12663         genIfxJump(ic,"a");
12664     }
12665     ic->generated = 1;
12666 }
12667
12668 /*-----------------------------------------------------------------*/
12669 /* genAddrOf - generates code for address of                       */
12670 /*-----------------------------------------------------------------*/
12671 static void genAddrOf (iCode *ic)
12672 {
12673   operand *result, *left;
12674   int size;
12675   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12676   pCodeOp *pcop0, *pcop1, *pcop2;
12677
12678     FENTRY;
12679
12680     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12681
12682     sym = OP_SYMBOL( IC_LEFT(ic) );
12683     
12684     if(sym->onStack) {
12685       /* get address of symbol on stack */
12686       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12687 #if 0
12688       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12689                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12690 #endif
12691
12692       // operands on stack are accessible via "FSR2 + index" with index
12693       // starting at 2 for arguments and growing from 0 downwards for
12694       // local variables (index == 0 is not assigned so we add one here)
12695       {
12696         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12697         if (soffs <= 0) {
12698           assert (soffs < 0);
12699           soffs++;
12700         } // if
12701         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12702         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12703         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12704         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12705         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12706         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12707         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12708       }
12709
12710       goto release;
12711     }
12712         
12713 //      if(pic16_debug_verbose) {
12714 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12715 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12716 //      }
12717         
12718     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12719     size = AOP_SIZE(IC_RESULT(ic));
12720
12721     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12722     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12723     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12724         
12725     if (size == 3) {
12726       pic16_emitpcode(POC_MOVLW, pcop0);
12727       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12728       pic16_emitpcode(POC_MOVLW, pcop1);
12729       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12730       pic16_emitpcode(POC_MOVLW, pcop2);
12731       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12732     } else
12733     if (size == 2) {
12734       pic16_emitpcode(POC_MOVLW, pcop0);
12735       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12736       pic16_emitpcode(POC_MOVLW, pcop1);
12737     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12738     } else {
12739       pic16_emitpcode(POC_MOVLW, pcop0);
12740       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12741     }
12742
12743     pic16_freeAsmop(left, NULL, ic, FALSE);
12744 release:
12745     pic16_freeAsmop(result,NULL,ic,TRUE);
12746 }
12747
12748
12749 #if 0
12750 /*-----------------------------------------------------------------*/
12751 /* genFarFarAssign - assignment when both are in far space         */
12752 /*-----------------------------------------------------------------*/
12753 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12754 {
12755     int size = AOP_SIZE(right);
12756     int offset = 0;
12757     char *l ;
12758     /* first push the right side on to the stack */
12759     while (size--) {
12760         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12761         MOVA(l);
12762         pic16_emitcode ("push","acc");
12763     }
12764     
12765     pic16_freeAsmop(right,NULL,ic,FALSE);
12766     /* now assign DPTR to result */
12767     pic16_aopOp(result,ic,FALSE);
12768     size = AOP_SIZE(result);
12769     while (size--) {
12770         pic16_emitcode ("pop","acc");
12771         pic16_aopPut(AOP(result),"a",--offset);
12772     }
12773     pic16_freeAsmop(result,NULL,ic,FALSE);
12774         
12775 }
12776 #endif
12777
12778 /*-----------------------------------------------------------------*/
12779 /* genAssign - generate code for assignment                        */
12780 /*-----------------------------------------------------------------*/
12781 static void genAssign (iCode *ic)
12782 {
12783   operand *result, *right;
12784   int size, offset,know_W;
12785   unsigned long lit = 0L;
12786
12787   result = IC_RESULT(ic);
12788   right  = IC_RIGHT(ic) ;
12789
12790   FENTRY;
12791   
12792   /* if they are the same */
12793   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12794     return ;
12795
12796   /* reversed order operands are aopOp'ed so that result operand
12797    * is effective in case right is a stack symbol. This maneauver
12798    * allows to use the _G.resDirect flag later */
12799   pic16_aopOp(result,ic,TRUE);
12800   pic16_aopOp(right,ic,FALSE);
12801
12802   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12803
12804   /* if they are the same registers */
12805   if (pic16_sameRegs(AOP(right),AOP(result)))
12806     goto release;
12807
12808   /* if the result is a bit */
12809   if (AOP_TYPE(result) == AOP_CRY) {
12810     /* if the right size is a literal then
12811        we know what the value is */
12812     if (AOP_TYPE(right) == AOP_LIT) {
12813           
12814       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12815                   pic16_popGet(AOP(result),0));
12816
12817       if (((int) operandLitValue(right))) 
12818         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12819                        AOP(result)->aopu.aop_dir,
12820                        AOP(result)->aopu.aop_dir);
12821       else
12822         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12823                        AOP(result)->aopu.aop_dir,
12824                        AOP(result)->aopu.aop_dir);
12825       goto release;
12826     }
12827
12828     /* the right is also a bit variable */
12829     if (AOP_TYPE(right) == AOP_CRY) {
12830       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12831       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12832       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12833
12834       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12835                      AOP(result)->aopu.aop_dir,
12836                      AOP(result)->aopu.aop_dir);
12837       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12838                      AOP(right)->aopu.aop_dir,
12839                      AOP(right)->aopu.aop_dir);
12840       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12841                      AOP(result)->aopu.aop_dir,
12842                      AOP(result)->aopu.aop_dir);
12843       goto release ;
12844     }
12845
12846     /* we need to or */
12847     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12848     pic16_toBoolean(right);
12849     emitSKPZ;
12850     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12851     //pic16_aopPut(AOP(result),"a",0);
12852     goto release ;
12853   }
12854
12855   /* bit variables done */
12856   /* general case */
12857   size = AOP_SIZE(result);
12858   offset = 0 ;
12859
12860   if(AOP_TYPE(right) == AOP_LIT) {
12861         if(!IS_FLOAT(operandType( right )))
12862                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12863         else {
12864            union {
12865               unsigned long lit_int;
12866               float lit_float;
12867             } info;
12868         
12869                 /* take care if literal is a float */
12870                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12871                 lit = info.lit_int;
12872         }
12873   }
12874
12875 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12876 //                      sizeof(unsigned long int), sizeof(float));
12877
12878
12879   if (AOP_TYPE(right) == AOP_REG) {
12880     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12881     while (size--) {
12882       
12883       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12884     } // while
12885     goto release;
12886   }
12887
12888   if(AOP_TYPE(right) != AOP_LIT
12889         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12890         && !IS_FUNC(OP_SYM_TYPE(right))
12891         ) {
12892         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12893         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12894
12895         // set up table pointer
12896         if(is_LitOp(right)) {
12897 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12898                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12899                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12900                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12901                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12902                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12903                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12904         } else {
12905 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12906                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12907                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12908                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12909                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12910                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12911                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12912         }
12913
12914         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12915         while(size--) {
12916                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12917                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12918                         pic16_popGet(AOP(result),offset)));
12919                 offset++;
12920         }
12921
12922         size = getSize(OP_SYM_ETYPE(right));
12923         if(AOP_SIZE(result) > size) {
12924                 size = AOP_SIZE(result) - size;
12925                 while(size--) {
12926                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12927                         offset++;
12928                 }
12929         }
12930         goto release;
12931   }
12932
12933
12934
12935 #if 0
12936 /* VR - What is this?! */
12937   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12938     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12939     if(aopIdx(AOP(result),0) == 4) {
12940
12941       /* this is a workaround to save value of right into wreg too,
12942        * value of wreg is going to be used later */
12943       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12944       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12945       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12946       goto release;
12947     } else
12948 //      assert(0);
12949       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12950   }
12951 #endif
12952
12953   know_W=-1;
12954   while (size--) {
12955   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12956     if(AOP_TYPE(right) == AOP_LIT) {
12957       if(lit&0xff) {
12958         if(know_W != (lit&0xff))
12959           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12960         know_W = lit&0xff;
12961         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12962       } else
12963         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12964
12965       lit >>= 8;
12966
12967     } else if (AOP_TYPE(right) == AOP_CRY) {
12968       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12969       if(offset == 0) {
12970         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12971         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12972         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12973       }
12974     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12975         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12976         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12977     } else {
12978       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12979
12980       if(!_G.resDirect)         /* use this aopForSym feature */
12981         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12982     }
12983             
12984     offset++;
12985   }
12986   
12987  release:
12988   pic16_freeAsmop (right,NULL,ic,FALSE);
12989   pic16_freeAsmop (result,NULL,ic,TRUE);
12990 }   
12991
12992 /*-----------------------------------------------------------------*/
12993 /* genJumpTab - generates code for jump table                       */
12994 /*-----------------------------------------------------------------*/
12995 static void genJumpTab (iCode *ic)
12996 {
12997   symbol *jtab;
12998   char *l;
12999   pCodeOp *jt_offs;
13000   pCodeOp *jt_offs_hi;
13001   pCodeOp *jt_label;
13002
13003     FENTRY;
13004
13005     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
13006     /* get the condition into accumulator */
13007     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13008     MOVA(l);
13009     /* multiply by three */
13010     pic16_emitcode("add","a,acc");
13011     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13012
13013     jtab = newiTempLabel(NULL);
13014     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13015     pic16_emitcode("jmp","@a+dptr");
13016     pic16_emitcode("","%05d_DS_:",jtab->key+100);
13017
13018 #if 0
13019     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13020     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13021     emitSKPNC;
13022     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13023     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13024     pic16_emitpLabel(jtab->key);
13025
13026 #else
13027
13028     jt_offs = pic16_popGetTempReg(0);
13029     jt_offs_hi = pic16_popGetTempReg(1);
13030     jt_label = pic16_popGetLabel (jtab->key);
13031     //fprintf (stderr, "Creating jump table...\n");
13032
13033     // calculate offset into jump table (idx * sizeof (GOTO))
13034     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13035     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13036     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13037     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13038     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13039     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13040     pic16_emitpcode(POC_MOVWF , jt_offs);
13041
13042     // prepare PCLATx (set to first entry in jump table)
13043     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13044     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13045     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13046     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13047     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13048
13049     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13050     pic16_emitpcode(POC_ADDWF , jt_offs);
13051     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13052     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13053     emitSKPNC;
13054     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13055
13056     // release temporaries and prepare jump into table (new PCL --> WREG)
13057     pic16_emitpcode(POC_MOVFW , jt_offs);
13058     pic16_popReleaseTempReg (jt_offs_hi, 1);
13059     pic16_popReleaseTempReg (jt_offs, 0);
13060
13061     // jump into the table
13062     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13063
13064     pic16_emitpLabelFORCE(jtab->key);
13065
13066 #endif
13067     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13068
13069     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13070     /* now generate the jump labels */
13071     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13072          jtab = setNextItem(IC_JTLABELS(ic))) {
13073 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13074         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13075         
13076     }
13077     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13078
13079 }
13080
13081 /*-----------------------------------------------------------------*/
13082 /* genMixedOperation - gen code for operators between mixed types  */
13083 /*-----------------------------------------------------------------*/
13084 /*
13085   TSD - Written for the PIC port - but this unfortunately is buggy.
13086   This routine is good in that it is able to efficiently promote 
13087   types to different (larger) sizes. Unfortunately, the temporary
13088   variables that are optimized out by this routine are sometimes
13089   used in other places. So until I know how to really parse the 
13090   iCode tree, I'm going to not be using this routine :(.
13091 */
13092 static int genMixedOperation (iCode *ic)
13093 {
13094 #if 0
13095   operand *result = IC_RESULT(ic);
13096   sym_link *ctype = operandType(IC_LEFT(ic));
13097   operand *right = IC_RIGHT(ic);
13098   int ret = 0;
13099   int big,small;
13100   int offset;
13101
13102   iCode *nextic;
13103   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13104
13105   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13106
13107   nextic = ic->next;
13108   if(!nextic)
13109     return 0;
13110
13111   nextright = IC_RIGHT(nextic);
13112   nextleft  = IC_LEFT(nextic);
13113   nextresult = IC_RESULT(nextic);
13114
13115   pic16_aopOp(right,ic,FALSE);
13116   pic16_aopOp(result,ic,FALSE);
13117   pic16_aopOp(nextright,  nextic, FALSE);
13118   pic16_aopOp(nextleft,   nextic, FALSE);
13119   pic16_aopOp(nextresult, nextic, FALSE);
13120
13121   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13122
13123     operand *t = right;
13124     right = nextright;
13125     nextright = t; 
13126
13127     pic16_emitcode(";remove right +","");
13128
13129   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13130 /*
13131     operand *t = right;
13132     right = nextleft;
13133     nextleft = t; 
13134 */
13135     pic16_emitcode(";remove left +","");
13136   } else
13137     return 0;
13138
13139   big = AOP_SIZE(nextleft);
13140   small = AOP_SIZE(nextright);
13141
13142   switch(nextic->op) {
13143
13144   case '+':
13145     pic16_emitcode(";optimize a +","");
13146     /* if unsigned or not an integral type */
13147     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13148       pic16_emitcode(";add a bit to something","");
13149     } else {
13150
13151       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13152
13153       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13154         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13155         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13156       } else
13157         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13158
13159       offset = 0;
13160       while(--big) {
13161
13162         offset++;
13163
13164         if(--small) {
13165           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13166             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13167             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13168           }
13169
13170           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13171           emitSKPNC;
13172           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13173                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13174                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13175           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13176           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13177
13178         } else {
13179           pic16_emitcode("rlf","known_zero,w");
13180
13181           /*
13182             if right is signed
13183               btfsc  right,7
13184                addlw ff
13185           */
13186           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13187             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13188             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13189           } else {
13190             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13191           }
13192         }
13193       }
13194       ret = 1;
13195     }
13196   }
13197   ret = 1;
13198
13199 release:
13200   pic16_freeAsmop(right,NULL,ic,TRUE);
13201   pic16_freeAsmop(result,NULL,ic,TRUE);
13202   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13203   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13204   if(ret)
13205     nextic->generated = 1;
13206
13207   return ret;
13208 #else
13209   return 0;
13210 #endif
13211 }
13212 /*-----------------------------------------------------------------*/
13213 /* genCast - gen code for casting                                  */
13214 /*-----------------------------------------------------------------*/
13215 static void genCast (iCode *ic)
13216 {
13217   operand *result = IC_RESULT(ic);
13218   sym_link *ctype = operandType(IC_LEFT(ic));
13219   sym_link *rtype = operandType(IC_RIGHT(ic));
13220   sym_link *restype = operandType(IC_RESULT(ic));
13221   operand *right = IC_RIGHT(ic);
13222   int size, offset ;
13223
13224
13225     FENTRY;
13226
13227         /* if they are equivalent then do nothing */
13228 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13229 //              return ;
13230
13231         pic16_aopOp(right,ic,FALSE) ;
13232         pic16_aopOp(result,ic,FALSE);
13233
13234         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13235
13236
13237         /* if the result is a bit */
13238         if (AOP_TYPE(result) == AOP_CRY) {
13239         
13240                 /* if the right size is a literal then
13241                  * we know what the value is */
13242                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13243
13244                 if (AOP_TYPE(right) == AOP_LIT) {
13245                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13246                                 pic16_popGet(AOP(result),0));
13247
13248                         if (((int) operandLitValue(right))) 
13249                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13250                                         AOP(result)->aopu.aop_dir,
13251                                         AOP(result)->aopu.aop_dir);
13252                         else
13253                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13254                                         AOP(result)->aopu.aop_dir,
13255                                         AOP(result)->aopu.aop_dir);
13256                         goto release;
13257                 }
13258
13259                 /* the right is also a bit variable */
13260                 if (AOP_TYPE(right) == AOP_CRY) {
13261                         emitCLRC;
13262                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13263
13264                         pic16_emitcode("clrc","");
13265                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13266                                 AOP(right)->aopu.aop_dir,
13267                                 AOP(right)->aopu.aop_dir);
13268                         pic16_aopPut(AOP(result),"c",0);
13269                         goto release ;
13270                 }
13271
13272                 /* we need to or */
13273                 if (AOP_TYPE(right) == AOP_REG) {
13274                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13275                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13276                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13277                 }
13278                 pic16_toBoolean(right);
13279                 pic16_aopPut(AOP(result),"a",0);
13280                 goto release ;
13281         }
13282
13283         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13284           int offset = 1;
13285
13286                 size = AOP_SIZE(result);
13287
13288                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13289
13290                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13291                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13292                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13293
13294                 while (size--)
13295                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13296
13297                 goto release;
13298         }
13299
13300         if(IS_BITFIELD(getSpec(restype))
13301           && IS_BITFIELD(getSpec(rtype))) {
13302           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13303         }
13304
13305         /* if they are the same size : or less */
13306         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13307
13308                 /* if they are in the same place */
13309                 if (pic16_sameRegs(AOP(right),AOP(result)))
13310                         goto release;
13311
13312                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13313 #if 0
13314                 if (IS_PTR_CONST(rtype))
13315 #else
13316                 if (IS_CODEPTR(rtype))
13317 #endif
13318                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13319
13320 #if 0
13321                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13322 #else
13323                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13324 #endif
13325                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13326
13327 #if 0
13328                 if(AOP_TYPE(right) == AOP_IMMD) {
13329                   pCodeOp *pcop0, *pcop1, *pcop2;
13330                   symbol *sym = OP_SYMBOL( right );
13331
13332                         size = AOP_SIZE(result);
13333                         /* low */
13334                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13335                         /* high */
13336                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13337                         /* upper */
13338                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13339         
13340                         if (size == 3) {
13341                                 pic16_emitpcode(POC_MOVLW, pcop0);
13342                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13343                                 pic16_emitpcode(POC_MOVLW, pcop1);
13344                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13345                                 pic16_emitpcode(POC_MOVLW, pcop2);
13346                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13347                         } else
13348                         if (size == 2) {
13349                                 pic16_emitpcode(POC_MOVLW, pcop0);
13350                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13351                                 pic16_emitpcode(POC_MOVLW, pcop1);
13352                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13353                         } else {
13354                                 pic16_emitpcode(POC_MOVLW, pcop0);
13355                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13356                         }
13357                 } else
13358 #endif
13359                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13360                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13361                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13362                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13363                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13364                         if(AOP_SIZE(result) <2)
13365                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13366                 } else {
13367                         /* if they in different places then copy */
13368                         size = AOP_SIZE(result);
13369                         offset = 0 ;
13370                         while (size--) {
13371                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13372                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13373                                 offset++;
13374                         }
13375                 }
13376                 goto release;
13377         }
13378
13379         /* if the result is of type pointer */
13380         if (IS_PTR(ctype)) {
13381           int p_type;
13382           sym_link *type = operandType(right);
13383           sym_link *etype = getSpec(type);
13384
13385                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13386
13387                 /* pointer to generic pointer */
13388                 if (IS_GENPTR(ctype)) {
13389                   char *l = zero;
13390             
13391                         if (IS_PTR(type)) 
13392                                 p_type = DCL_TYPE(type);
13393                         else {
13394                 /* we have to go by the storage class */
13395                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13396
13397 /*              if (SPEC_OCLS(etype)->codesp )  */
13398 /*                  p_type = CPOINTER ;  */
13399 /*              else */
13400 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13401 /*                      p_type = FPOINTER ; */
13402 /*                  else */
13403 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13404 /*                          p_type = PPOINTER; */
13405 /*                      else */
13406 /*                          if (SPEC_OCLS(etype) == idata ) */
13407 /*                              p_type = IPOINTER ; */
13408 /*                          else */
13409 /*                              p_type = POINTER ; */
13410             }
13411                 
13412             /* the first two bytes are known */
13413       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13414             size = GPTRSIZE - 1; 
13415             offset = 0 ;
13416             while (size--) {
13417               if(offset < AOP_SIZE(right)) {
13418                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13419                 mov2f(AOP(result), AOP(right), offset);
13420 /*
13421                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13422                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13423                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13424                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13425                 } else { 
13426                   
13427                   pic16_aopPut(AOP(result),
13428                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13429                          offset);
13430                 }
13431 */
13432               } else 
13433                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13434               offset++;
13435             }
13436             /* the last byte depending on type */
13437             switch (p_type) {
13438             case IPOINTER:
13439             case POINTER:
13440                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13441                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13442 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13443                 break;
13444
13445             case CPOINTER:
13446                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13447                 break;
13448
13449             case FPOINTER:
13450               pic16_emitcode(";BUG!? ","%d",__LINE__);
13451                 l = one;
13452                 break;
13453             case PPOINTER:
13454               pic16_emitcode(";BUG!? ","%d",__LINE__);
13455                 l = "#0x03";
13456                 break;
13457
13458             case GPOINTER:
13459                 if (GPTRSIZE > AOP_SIZE(right)) {
13460                   // assume data pointer... THIS MIGHT BE WRONG!
13461                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13462                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13463                 } else {
13464                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13465                 }
13466               break;
13467               
13468             default:
13469                 /* this should never happen */
13470                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13471                        "got unknown pointer type");
13472                 exit(1);
13473             }
13474             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13475             goto release ;
13476         }
13477         
13478         /* just copy the pointers */
13479         size = AOP_SIZE(result);
13480         offset = 0 ;
13481         while (size--) {
13482             pic16_aopPut(AOP(result),
13483                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13484                    offset);
13485             offset++;
13486         }
13487         goto release ;
13488     }
13489     
13490
13491
13492     /* so we now know that the size of destination is greater
13493     than the size of the source.
13494     Now, if the next iCode is an operator then we might be
13495     able to optimize the operation without performing a cast.
13496     */
13497     if(genMixedOperation(ic))
13498       goto release;
13499
13500     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13501     
13502     /* we move to result for the size of source */
13503     size = AOP_SIZE(right);
13504     offset = 0 ;
13505     while (size--) {
13506       mov2f(AOP(result), AOP(right), offset);
13507       offset++;
13508     }
13509
13510     /* now depending on the sign of the destination */
13511     size = AOP_SIZE(result) - AOP_SIZE(right);
13512     /* if unsigned or not an integral type */
13513     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13514       while (size--)
13515         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13516     } else {
13517       /* we need to extend the sign :( */
13518
13519       if(size == 1) {
13520         /* Save one instruction of casting char to int */
13521         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13522         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13523         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13524       } else {
13525         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13526
13527         if(offset)
13528           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13529         else
13530           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13531         
13532         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13533
13534         while (size--)
13535           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13536       }
13537     }
13538
13539 release:
13540     pic16_freeAsmop(right,NULL,ic,TRUE);
13541     pic16_freeAsmop(result,NULL,ic,TRUE);
13542
13543 }
13544
13545 /*-----------------------------------------------------------------*/
13546 /* genDjnz - generate decrement & jump if not zero instrucion      */
13547 /*-----------------------------------------------------------------*/
13548 static int genDjnz (iCode *ic, iCode *ifx)
13549 {
13550     symbol *lbl, *lbl1;
13551     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13552
13553     if (!ifx)
13554         return 0;
13555     
13556     /* if the if condition has a false label
13557        then we cannot save */
13558     if (IC_FALSE(ifx))
13559         return 0;
13560
13561     /* if the minus is not of the form 
13562        a = a - 1 */
13563     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13564         !IS_OP_LITERAL(IC_RIGHT(ic)))
13565         return 0;
13566
13567     if (operandLitValue(IC_RIGHT(ic)) != 1)
13568         return 0;
13569
13570     /* if the size of this greater than one then no
13571        saving */
13572     if (getSize(operandType(IC_RESULT(ic))) > 1)
13573         return 0;
13574
13575     /* otherwise we can save BIG */
13576     lbl = newiTempLabel(NULL);
13577     lbl1= newiTempLabel(NULL);
13578
13579     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13580     
13581     if (IS_AOP_PREG(IC_RESULT(ic))) {
13582         pic16_emitcode("dec","%s",
13583                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13584         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13585         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13586     } else {    
13587
13588
13589       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13590       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13591
13592       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13593       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13594
13595     }
13596     
13597     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13598     ifx->generated = 1;
13599     return 1;
13600 }
13601
13602 /*-----------------------------------------------------------------*/
13603 /* genReceive - generate code for a receive iCode                  */
13604 /*-----------------------------------------------------------------*/
13605 static void genReceive (iCode *ic)
13606 {    
13607
13608   FENTRY;
13609
13610 #if 0
13611   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13612         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13613 #endif
13614 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13615
13616   if (isOperandInFarSpace(IC_RESULT(ic))
13617       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13618           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13619
13620     int size = getSize(operandType(IC_RESULT(ic)));
13621     int offset =  pic16_fReturnSizePic - size;
13622
13623       assert( 0 );
13624       while (size--) {
13625         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13626                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13627                       offset++;
13628         }
13629
13630       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13631
13632       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13633       size = AOP_SIZE(IC_RESULT(ic));
13634       offset = 0;
13635       while (size--) {
13636         pic16_emitcode ("pop","acc");
13637         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13638       }
13639   } else {
13640     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13641     _G.accInUse++;
13642     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13643     _G.accInUse--;
13644
13645     /* set pseudo stack pointer to where it should be - dw*/
13646     GpsuedoStkPtr = ic->parmBytes;
13647
13648     /* setting GpsuedoStkPtr has side effects here: */
13649     assignResultValue(IC_RESULT(ic), 0);
13650   }
13651
13652   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13653 }
13654
13655 /*-----------------------------------------------------------------*/
13656 /* genDummyRead - generate code for dummy read of volatiles        */
13657 /*-----------------------------------------------------------------*/
13658 static void
13659 genDummyRead (iCode * ic)
13660 {
13661   operand *op;
13662   int i;
13663
13664   op = IC_RIGHT(ic);
13665   if (op && IS_SYMOP(op)) {
13666     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13667       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13668       return;
13669     }
13670     pic16_aopOp (op, ic, FALSE);
13671     for (i=0; i < AOP_SIZE(op); i++) {
13672       // may need to protect this from the peepholer -- this is not nice but works...
13673       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13674       pic16_mov2w (AOP(op),i);
13675       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13676     } // for i
13677     pic16_freeAsmop (op, NULL, ic, TRUE);
13678   } else if (op) {
13679     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13680   } // if
13681 }
13682
13683 /*-----------------------------------------------------------------*/
13684 /* genpic16Code - generate code for pic16 based controllers        */
13685 /*-----------------------------------------------------------------*/
13686 /*
13687  * At this point, ralloc.c has gone through the iCode and attempted
13688  * to optimize in a way suitable for a PIC. Now we've got to generate
13689  * PIC instructions that correspond to the iCode.
13690  *
13691  * Once the instructions are generated, we'll pass through both the
13692  * peep hole optimizer and the pCode optimizer.
13693  *-----------------------------------------------------------------*/
13694
13695 void genpic16Code (iCode *lic)
13696 {
13697   iCode *ic;
13698   int cln = 0;
13699
13700     lineHead = lineCurr = NULL;
13701
13702     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13703     pic16_addpBlock(pb);
13704
13705 #if 0
13706     /* if debug information required */
13707     if (options.debug && currFunc) {
13708       if (currFunc) {
13709         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13710       }
13711     }
13712 #endif
13713
13714     for (ic = lic ; ic ; ic = ic->next ) {
13715
13716       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13717       if ( cln != ic->lineno ) {
13718         if ( options.debug ) {
13719           debugFile->writeCLine (ic);
13720         }
13721         
13722         if(!options.noCcodeInAsm) {
13723           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13724               printCLine(ic->filename, ic->lineno)));
13725         }
13726
13727         cln = ic->lineno ;
13728       }
13729         
13730       if(options.iCodeInAsm) {
13731         char *l;
13732
13733           /* insert here code to print iCode as comment */
13734           l = Safe_strdup(printILine(ic));
13735           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13736       }
13737         
13738       /* if the result is marked as
13739        * spilt and rematerializable or code for
13740        * this has already been generated then
13741        * do nothing */
13742       if (resultRemat(ic) || ic->generated ) 
13743         continue ;
13744         
13745       /* depending on the operation */
13746       switch (ic->op) {
13747         case '!' :
13748           pic16_genNot(ic);
13749           break;
13750             
13751         case '~' :
13752           pic16_genCpl(ic);
13753           break;
13754             
13755         case UNARYMINUS:
13756           genUminus (ic);
13757           break;
13758             
13759         case IPUSH:
13760           genIpush (ic);
13761           break;
13762             
13763         case IPOP:
13764           /* IPOP happens only when trying to restore a 
13765            * spilt live range, if there is an ifx statement
13766            * following this pop then the if statement might
13767            * be using some of the registers being popped which
13768            * would destroy the contents of the register so
13769            * we need to check for this condition and handle it */
13770            if (ic->next
13771              && ic->next->op == IFX
13772              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13773                genIfx (ic->next,ic);
13774           else
13775             genIpop (ic);
13776           break; 
13777             
13778         case CALL:
13779           genCall (ic);
13780           break;
13781             
13782         case PCALL:
13783           genPcall (ic);
13784           break;
13785             
13786         case FUNCTION:
13787           genFunction (ic);
13788           break;
13789             
13790         case ENDFUNCTION:
13791           genEndFunction (ic);
13792           break;
13793             
13794         case RETURN:
13795           genRet (ic);
13796           break;
13797             
13798         case LABEL:
13799           genLabel (ic);
13800           break;
13801             
13802         case GOTO:
13803           genGoto (ic);
13804           break;
13805             
13806         case '+' :
13807           pic16_genPlus (ic) ;
13808           break;
13809             
13810         case '-' :
13811           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13812             pic16_genMinus (ic);
13813           break;
13814
13815         case '*' :
13816           genMult (ic);
13817           break;
13818             
13819         case '/' :
13820           genDiv (ic) ;
13821           break;
13822             
13823         case '%' :
13824           genMod (ic);
13825           break;
13826             
13827         case '>' :
13828           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13829           break;
13830             
13831         case '<' :
13832           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13833           break;
13834             
13835         case LE_OP:
13836         case GE_OP:
13837         case NE_OP:
13838           /* note these two are xlated by algebraic equivalence
13839            * during parsing SDCC.y */
13840           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13841             "got '>=' or '<=' shouldn't have come here");
13842           break;
13843
13844         case EQ_OP:
13845           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13846           break;            
13847             
13848         case AND_OP:
13849           genAndOp (ic);
13850           break;
13851             
13852         case OR_OP:
13853           genOrOp (ic);
13854           break;
13855             
13856         case '^' :
13857           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13858           break;
13859             
13860         case '|' :
13861           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13862           break;
13863             
13864         case BITWISEAND:
13865           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13866           break;
13867             
13868         case INLINEASM:
13869           genInline (ic);
13870           break;
13871             
13872         case RRC:
13873           genRRC (ic);
13874           break;
13875             
13876         case RLC:
13877           genRLC (ic);
13878           break;
13879             
13880         case GETHBIT:
13881           genGetHbit (ic);
13882           break;
13883             
13884         case LEFT_OP:
13885           genLeftShift (ic);
13886           break;
13887             
13888         case RIGHT_OP:
13889           genRightShift (ic);
13890           break;
13891             
13892         case GET_VALUE_AT_ADDRESS:
13893           genPointerGet(ic);
13894           break;
13895             
13896         case '=' :
13897           if (POINTER_SET(ic))
13898             genPointerSet(ic);
13899           else
13900             genAssign(ic);
13901           break;
13902             
13903         case IFX:
13904           genIfx (ic,NULL);
13905           break;
13906             
13907         case ADDRESS_OF:
13908           genAddrOf (ic);
13909           break;
13910             
13911         case JUMPTABLE:
13912           genJumpTab (ic);
13913           break;
13914             
13915         case CAST:
13916           genCast (ic);
13917           break;
13918             
13919         case RECEIVE:
13920           genReceive(ic);
13921           break;
13922             
13923         case SEND:
13924           addSet(&_G.sendSet,ic);
13925           break;
13926
13927         case DUMMY_READ_VOLATILE:
13928           genDummyRead (ic);
13929           break;
13930
13931         default :
13932           ic = ic;
13933       }
13934     }
13935
13936
13937     /* now we are ready to call the
13938        peep hole optimizer */
13939     if (!options.nopeep)
13940       peepHole (&lineHead);
13941
13942     /* now do the actual printing */
13943     printLine (lineHead, codeOutFile);
13944
13945 #ifdef PCODE_DEBUG
13946     DFPRINTF((stderr,"printing pBlock\n\n"));
13947     pic16_printpBlock(stdout,pb);
13948 #endif
13949
13950     return;
13951 }
13952