* src/pic16/gen.c (genAssign): fixed assignment from longs
[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 0
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->size = AOP_SIZE( IC_LEFT(ic) );
873         else if(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   if(is_LitOp(op)) {
3901     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3902       if(lit == 0) {
3903         pic16_emitpcode(POC_CLRF, dest);
3904       } else {
3905         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3906         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3907       }
3908   } else {
3909     if(dest->type == PO_WREG && (offset == 0)) {
3910       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3911       return;
3912     }
3913     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3914   }
3915 }
3916
3917 /*-----------------------------------------------------------------*/
3918 /* genRet - generate code for return statement                     */
3919 /*-----------------------------------------------------------------*/
3920 static void genRet (iCode *ic)
3921 {
3922   int size;
3923   operand *left;
3924
3925     FENTRY;
3926         /* if we have no return value then
3927          * just generate the "ret" */
3928         
3929         if (!IC_LEFT(ic)) 
3930                 goto jumpret;       
3931     
3932         /* we have something to return then
3933          * move the return value into place */
3934         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3935         size = AOP_SIZE(IC_LEFT(ic));
3936
3937         if(size <= 4) {
3938                 if(size>3) {
3939                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3940 //                      pic16_emitpcode(POC_MOVFF,
3941 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3942                 }
3943                 if(size>2) {
3944                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3945 //                      pic16_emitpcode(POC_MOVFF,
3946 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3947                 }
3948                 if(size>1) {
3949                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3950 //                      pic16_emitpcode(POC_MOVFF,
3951 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3952                 }
3953
3954 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3955
3956                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3957 //              pic16_emitpcode(POC_MOVFF,
3958 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3959
3960         } else {
3961                 /* >32-bits, setup stack and FSR0 */
3962                 while (size--) {
3963 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3964 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3965
3966                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3967
3968 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3969                         GpsuedoStkPtr++;
3970                 }
3971                         
3972                 /* setup FSR0 */
3973                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3974                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3975
3976                 if(STACK_MODEL_LARGE) {
3977                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3978                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3979                 } else {
3980                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3981                 }
3982         }
3983                                 
3984 #if 0
3985         /* old code, left here for reference -- VR */    
3986         while (size--) {
3987           char *l ;
3988
3989                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3990                         /* #NOCHANGE */
3991                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3992                         pic16_emitpcomment("push %s",l);
3993                         pushed++;
3994                 } else {
3995                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3996                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3997                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3998                         
3999                         if (strcmp(fReturn[offset],l)) {
4000                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4001                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4002                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4003                                 } else {
4004                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4005                                 }
4006                                 
4007                                 if(size) {
4008                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4009                                 }
4010                                 offset++;
4011                         }
4012                 }
4013         }    
4014
4015         if (pushed) {
4016                 while(pushed) {
4017                         pushed--;
4018                         if (strcmp(fReturn[pushed],"a"))
4019                                 pic16_emitcode("pop",fReturn[pushed]);
4020                         else
4021                                 pic16_emitcode("pop","acc");
4022                 }
4023         }
4024 #endif
4025
4026
4027         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4028     
4029 jumpret:
4030         /* generate a jump to the return label
4031          * if the next is not the return statement */
4032         if (!(ic->next && ic->next->op == LABEL
4033                 && IC_LABEL(ic->next) == returnLabel)) {
4034         
4035                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4036                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4037         }
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genLabel - generates a label                                    */
4042 /*-----------------------------------------------------------------*/
4043 static void genLabel (iCode *ic)
4044 {
4045   FENTRY;
4046
4047   /* special case never generate */
4048   if (IC_LABEL(ic) == entryLabel)
4049     return ;
4050
4051   pic16_emitpLabel(IC_LABEL(ic)->key);
4052 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4053 }
4054
4055 /*-----------------------------------------------------------------*/
4056 /* genGoto - generates a goto                                      */
4057 /*-----------------------------------------------------------------*/
4058 //tsd
4059 static void genGoto (iCode *ic)
4060 {
4061   FENTRY;
4062   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4063 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4064 }
4065
4066
4067 /*-----------------------------------------------------------------*/
4068 /* genMultbits :- multiplication of bits                           */
4069 /*-----------------------------------------------------------------*/
4070 static void genMultbits (operand *left, 
4071                          operand *right, 
4072                          operand *result)
4073 {
4074   FENTRY;
4075
4076   if(!pic16_sameRegs(AOP(result),AOP(right)))
4077     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4078
4079   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4080   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4081   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4082
4083 }
4084
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genMultOneByte : 8 bit multiplication & division                */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultOneByte (operand *left,
4090                             operand *right,
4091                             operand *result)
4092 {
4093
4094   FENTRY;
4095   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4096   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4097
4098   /* (if two literals, the value is computed before) */
4099   /* if one literal, literal on the right */
4100   if (AOP_TYPE(left) == AOP_LIT){
4101     operand *t = right;
4102     right = left;
4103     left = t;
4104   }
4105
4106         /* size is already checked in genMult == 1 */
4107 //      size = AOP_SIZE(result);
4108
4109         if (AOP_TYPE(right) == AOP_LIT){
4110                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4111                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4112                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4113                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4114         } else {
4115                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4116                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4117                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4118                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4119         }
4120         
4121         pic16_genMult8X8_8 (left, right,result);
4122 }
4123
4124 /*-----------------------------------------------------------------*/
4125 /* genMultOneWord : 16 bit multiplication                          */
4126 /*-----------------------------------------------------------------*/
4127 static void genMultOneWord (operand *left,
4128                             operand *right,
4129                             operand *result)
4130 {
4131   FENTRY;
4132   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4133   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4134
4135   /* (if two literals, the value is computed before)
4136    * if one literal, literal on the right */
4137   if (AOP_TYPE(left) == AOP_LIT){
4138     operand *t = right;
4139     right = left;
4140     left = t;
4141   }
4142
4143   /* size is checked already == 2 */
4144 //  size = AOP_SIZE(result);
4145
4146   if (AOP_TYPE(right) == AOP_LIT) {
4147     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4148       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4149       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4150       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4151   } else {
4152     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4153       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4154       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4155       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4156   }
4157         
4158   pic16_genMult16X16_16(left, right,result);
4159 }
4160
4161 /*-----------------------------------------------------------------*/
4162 /* genMultOneLong : 32 bit multiplication                          */
4163 /*-----------------------------------------------------------------*/
4164 static void genMultOneLong (operand *left,
4165                             operand *right,
4166                             operand *result)
4167 {
4168   FENTRY;
4169   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4170   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4171
4172   /* (if two literals, the value is computed before)
4173    * if one literal, literal on the right */
4174   if (AOP_TYPE(left) == AOP_LIT){
4175     operand *t = right;
4176     right = left;
4177     left = t;
4178   }
4179
4180   /* size is checked already == 4 */
4181 //  size = AOP_SIZE(result);
4182
4183   if (AOP_TYPE(right) == AOP_LIT) {
4184     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4185         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4186         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4187         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4188   } else {
4189     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4190         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4191         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4192         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4193   }
4194         
4195   pic16_genMult32X32_32(left, right,result);
4196 }
4197
4198
4199
4200 /*-----------------------------------------------------------------*/
4201 /* genMult - generates code for multiplication                     */
4202 /*-----------------------------------------------------------------*/
4203 static void genMult (iCode *ic)
4204 {
4205   operand *left = IC_LEFT(ic);
4206   operand *right = IC_RIGHT(ic);
4207   operand *result= IC_RESULT(ic);   
4208
4209     FENTRY;
4210         /* assign the amsops */
4211         pic16_aopOp (left,ic,FALSE);
4212         pic16_aopOp (right,ic,FALSE);
4213         pic16_aopOp (result,ic,TRUE);
4214
4215         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216
4217         /* special cases first *
4218         * both are bits */
4219         if (AOP_TYPE(left) == AOP_CRY
4220                 && AOP_TYPE(right)== AOP_CRY) {
4221                 genMultbits(left,right,result);
4222           goto release ;
4223         }
4224
4225         /* if both are of size == 1 */
4226         if(AOP_SIZE(left) == 1
4227                 && AOP_SIZE(right) == 1) {
4228                 genMultOneByte(left,right,result);
4229           goto release ;
4230         }
4231
4232         /* if both are of size == 2 */
4233         if(AOP_SIZE(left) == 2
4234                 && AOP_SIZE(right) == 2) {
4235                 genMultOneWord(left, right, result);
4236           goto release;
4237         }
4238         
4239         /* if both are of size == 4 */
4240         if(AOP_SIZE(left) == 4
4241                 && AOP_SIZE(right) == 4) {
4242                 genMultOneLong(left, right, result);
4243           goto release;
4244         }
4245         
4246         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4247
4248
4249         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4250         /* should have been converted to function call */
4251         assert(0) ;
4252
4253 release :
4254         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4256         pic16_freeAsmop(result,NULL,ic,TRUE); 
4257 }
4258
4259 /*-----------------------------------------------------------------*/
4260 /* genDivbits :- division of bits                                  */
4261 /*-----------------------------------------------------------------*/
4262 static void genDivbits (operand *left, 
4263                         operand *right, 
4264                         operand *result)
4265 {
4266   char *l;
4267
4268     FENTRY;
4269     /* the result must be bit */    
4270     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4271     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4272
4273     MOVA(l);    
4274
4275     pic16_emitcode("div","ab");
4276     pic16_emitcode("rrc","a");
4277     pic16_aopPut(AOP(result),"c",0);
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genDivOneByte : 8 bit division                                  */
4282 /*-----------------------------------------------------------------*/
4283 static void genDivOneByte (operand *left,
4284                            operand *right,
4285                            operand *result)
4286 {
4287   sym_link *opetype = operandType(result);
4288   char *l ;
4289   symbol *lbl ;
4290   int size,offset;
4291
4292         /* result = divident / divisor
4293          * - divident may be a register or a literal,
4294          * - divisor may be a register or a literal,
4295          * so there are 3 cases (literal / literal is optimized
4296          * by the front-end) to handle.
4297          * In addition we must handle signed and unsigned, which
4298          * result in 6 final different cases -- VR */
4299
4300     FENTRY;
4301     
4302     size = AOP_SIZE(result) - 1;
4303     offset = 1;
4304     /* signed or unsigned */
4305     if (SPEC_USIGN(opetype)) {
4306       pCodeOp *pct1,    /* count */
4307                 *pct2,  /* reste */
4308                 *pct3;  /* temp */
4309       symbol *label1, *label2, *label3;;
4310
4311
4312         /* unsigned is easy */
4313
4314         pct1 = pic16_popGetTempReg(1);
4315         pct2 = pic16_popGetTempReg(1);
4316         pct3 = pic16_popGetTempReg(1);
4317         
4318         label1 = newiTempLabel(NULL);
4319         label2 = newiTempLabel(NULL);
4320         label3 = newiTempLabel(NULL);
4321
4322         /* the following algorithm is extracted from divuint.c */
4323
4324         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4325         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4326         
4327         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4328
4329         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4330         
4331         pic16_emitpLabel(label1->key);
4332         
4333         emitCLRC;
4334         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4335
4336
4337         emitCLRC;
4338         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4339         
4340
4341         emitSKPNC;
4342         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4343         
4344         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4345         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4346         
4347         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4348         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4349         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4350         
4351         pic16_emitpLabel( label3->key );
4352         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4353         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4354         
4355         
4356
4357         pic16_emitpLabel(label2->key);
4358         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4359         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4360         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4361         
4362         /* result is in wreg */
4363         if(AOP_TYPE(result) != AOP_ACC)
4364                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4365
4366         pic16_popReleaseTempReg( pct3, 1);
4367         pic16_popReleaseTempReg( pct2, 1);
4368         pic16_popReleaseTempReg( pct1, 1);
4369
4370         return ;
4371     }
4372
4373     /* signed is a little bit more difficult */
4374
4375     /* save the signs of the operands */
4376     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4377     MOVA(l);    
4378     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4379     pic16_emitcode("push","acc"); /* save it on the stack */
4380
4381     /* now sign adjust for both left & right */
4382     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4383     MOVA(l);       
4384     lbl = newiTempLabel(NULL);
4385     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4386     pic16_emitcode("cpl","a");   
4387     pic16_emitcode("inc","a");
4388     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4389     pic16_emitcode("mov","b,a");
4390
4391     /* sign adjust left side */
4392     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4393     MOVA(l);
4394
4395     lbl = newiTempLabel(NULL);
4396     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4397     pic16_emitcode("cpl","a");
4398     pic16_emitcode("inc","a");
4399     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4400
4401     /* now the division */
4402     pic16_emitcode("div","ab");
4403     /* we are interested in the lower order
4404     only */
4405     pic16_emitcode("mov","b,a");
4406     lbl = newiTempLabel(NULL);
4407     pic16_emitcode("pop","acc");   
4408     /* if there was an over flow we don't 
4409     adjust the sign of the result */
4410     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4411     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4412     CLRC;
4413     pic16_emitcode("clr","a");
4414     pic16_emitcode("subb","a,b");
4415     pic16_emitcode("mov","b,a");
4416     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417
4418     /* now we are done */
4419     pic16_aopPut(AOP(result),"b",0);
4420     if(size > 0){
4421         pic16_emitcode("mov","c,b.7");
4422         pic16_emitcode("subb","a,acc");   
4423     }
4424     while (size--)
4425         pic16_aopPut(AOP(result),"a",offset++);
4426
4427 }
4428
4429 /*-----------------------------------------------------------------*/
4430 /* genDiv - generates code for division                            */
4431 /*-----------------------------------------------------------------*/
4432 static void genDiv (iCode *ic)
4433 {
4434     operand *left = IC_LEFT(ic);
4435     operand *right = IC_RIGHT(ic);
4436     operand *result= IC_RESULT(ic);   
4437
4438
4439         /* Division is a very lengthy algorithm, so it is better
4440          * to call support routines than inlining algorithm.
4441          * Division functions written here just in case someone
4442          * wants to inline and not use the support libraries -- VR */
4443
4444     FENTRY;
4445     
4446     /* assign the amsops */
4447     pic16_aopOp (left,ic,FALSE);
4448     pic16_aopOp (right,ic,FALSE);
4449     pic16_aopOp (result,ic,TRUE);
4450
4451     /* special cases first */
4452     /* both are bits */
4453     if (AOP_TYPE(left) == AOP_CRY &&
4454         AOP_TYPE(right)== AOP_CRY) {
4455         genDivbits(left,right,result);
4456         goto release ;
4457     }
4458
4459     /* if both are of size == 1 */
4460     if (AOP_SIZE(left) == 1 &&
4461         AOP_SIZE(right) == 1 ) {
4462         genDivOneByte(left,right,result);
4463         goto release ;
4464     }
4465
4466     /* should have been converted to function call */
4467     assert(0);
4468 release :
4469     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4471     pic16_freeAsmop(result,NULL,ic,TRUE); 
4472 }
4473
4474 /*-----------------------------------------------------------------*/
4475 /* genModbits :- modulus of bits                                   */
4476 /*-----------------------------------------------------------------*/
4477 static void genModbits (operand *left, 
4478                         operand *right, 
4479                         operand *result)
4480 {
4481   char *l;
4482
4483     FENTRY;  
4484     
4485     werror(W_POSSBUG2, __FILE__, __LINE__);
4486     /* the result must be bit */    
4487     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4488     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4489
4490     MOVA(l);       
4491
4492     pic16_emitcode("div","ab");
4493     pic16_emitcode("mov","a,b");
4494     pic16_emitcode("rrc","a");
4495     pic16_aopPut(AOP(result),"c",0);
4496 }
4497
4498 /*-----------------------------------------------------------------*/
4499 /* genModOneByte : 8 bit modulus                                   */
4500 /*-----------------------------------------------------------------*/
4501 static void genModOneByte (operand *left,
4502                            operand *right,
4503                            operand *result)
4504 {
4505   sym_link *opetype = operandType(result);
4506   char *l ;
4507   symbol *lbl ;
4508
4509     FENTRY;
4510     werror(W_POSSBUG2, __FILE__, __LINE__);
4511
4512     /* signed or unsigned */
4513     if (SPEC_USIGN(opetype)) {
4514         /* unsigned is easy */
4515         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4516         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4517         MOVA(l);    
4518         pic16_emitcode("div","ab");
4519         pic16_aopPut(AOP(result),"b",0);
4520         return ;
4521     }
4522
4523     /* signed is a little bit more difficult */
4524
4525     /* save the signs of the operands */
4526     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4527     MOVA(l);
4528
4529     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4530     pic16_emitcode("push","acc"); /* save it on the stack */
4531
4532     /* now sign adjust for both left & right */
4533     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4534     MOVA(l);
4535
4536     lbl = newiTempLabel(NULL);
4537     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4538     pic16_emitcode("cpl","a");   
4539     pic16_emitcode("inc","a");
4540     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4541     pic16_emitcode("mov","b,a"); 
4542
4543     /* sign adjust left side */
4544     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4545     MOVA(l);
4546
4547     lbl = newiTempLabel(NULL);
4548     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4549     pic16_emitcode("cpl","a");   
4550     pic16_emitcode("inc","a");
4551     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4552
4553     /* now the multiplication */
4554     pic16_emitcode("div","ab");
4555     /* we are interested in the lower order
4556     only */
4557     lbl = newiTempLabel(NULL);
4558     pic16_emitcode("pop","acc");   
4559     /* if there was an over flow we don't 
4560     adjust the sign of the result */
4561     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4562     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4563     CLRC ;
4564     pic16_emitcode("clr","a");
4565     pic16_emitcode("subb","a,b");
4566     pic16_emitcode("mov","b,a");
4567     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4568
4569     /* now we are done */
4570     pic16_aopPut(AOP(result),"b",0);
4571
4572 }
4573
4574 /*-----------------------------------------------------------------*/
4575 /* genMod - generates code for division                            */
4576 /*-----------------------------------------------------------------*/
4577 static void genMod (iCode *ic)
4578 {
4579   operand *left = IC_LEFT(ic);
4580   operand *right = IC_RIGHT(ic);
4581   operand *result= IC_RESULT(ic);  
4582
4583     FENTRY;
4584     
4585     /* assign the amsops */
4586     pic16_aopOp (left,ic,FALSE);
4587     pic16_aopOp (right,ic,FALSE);
4588     pic16_aopOp (result,ic,TRUE);
4589
4590     /* special cases first */
4591     /* both are bits */
4592     if (AOP_TYPE(left) == AOP_CRY &&
4593         AOP_TYPE(right)== AOP_CRY) {
4594         genModbits(left,right,result);
4595         goto release ;
4596     }
4597
4598     /* if both are of size == 1 */
4599     if (AOP_SIZE(left) == 1 &&
4600         AOP_SIZE(right) == 1 ) {
4601         genModOneByte(left,right,result);
4602         goto release ;
4603     }
4604
4605     /* should have been converted to function call */
4606     assert(0);
4607
4608 release :
4609     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4611     pic16_freeAsmop(result,NULL,ic,TRUE); 
4612 }
4613
4614 /*-----------------------------------------------------------------*/
4615 /* genIfxJump :- will create a jump depending on the ifx           */
4616 /*-----------------------------------------------------------------*/
4617 /*
4618   note: May need to add parameter to indicate when a variable is in bit space.
4619 */
4620 static void genIfxJump (iCode *ic, char *jval)
4621 {
4622   FENTRY;
4623   
4624     /* if true label then we jump if condition
4625     supplied is true */
4626     if ( IC_TRUE(ic) ) {
4627
4628         if(strcmp(jval,"a") == 0)
4629           emitSKPZ;
4630         else if (strcmp(jval,"c") == 0)
4631           emitSKPNC;
4632         else {
4633           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4634           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4635         }
4636
4637         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4638         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4639
4640     }
4641     else {
4642         /* false label is present */
4643         if(strcmp(jval,"a") == 0)
4644           emitSKPNZ;
4645         else if (strcmp(jval,"c") == 0)
4646           emitSKPC;
4647         else {
4648           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4649           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4650         }
4651
4652         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4653         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4654
4655     }
4656
4657
4658     /* mark the icode as generated */
4659     ic->generated = 1;
4660 }
4661
4662 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4663 {
4664   FENTRY;
4665   
4666     /* if true label then we jump if condition
4667     supplied is true */
4668     if ( IC_TRUE(ic) ) {
4669       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4670       pic16_emitpcode(POC_BTFSC, jop);
4671
4672       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4673       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4674
4675     } else {
4676       /* false label is present */
4677       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4678       pic16_emitpcode(POC_BTFSS, jop);
4679           
4680       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4681       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4682     }
4683
4684
4685     /* mark the icode as generated */
4686     ic->generated = 1;
4687 }
4688
4689 #if 0
4690 // not needed ATM
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genSkip                                                         */
4694 /*-----------------------------------------------------------------*/
4695 static void genSkip(iCode *ifx,int status_bit)
4696 {
4697   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4698   if(!ifx)
4699     return;
4700
4701   if ( IC_TRUE(ifx) ) {
4702     switch(status_bit) {
4703     case 'z':
4704       emitSKPNZ;
4705       break;
4706
4707     case 'c':
4708       emitSKPNC;
4709       break;
4710
4711     case 'd':
4712       emitSKPDC;
4713       break;
4714
4715     }
4716
4717     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4718     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4719
4720   } else {
4721
4722     switch(status_bit) {
4723
4724     case 'z':
4725       emitSKPZ;
4726       break;
4727
4728     case 'c':
4729       emitSKPC;
4730       break;
4731
4732     case 'd':
4733       emitSKPDC;
4734       break;
4735     }
4736     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4737     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4738
4739   }
4740
4741 }
4742 #endif
4743
4744 /*-----------------------------------------------------------------*/
4745 /* genSkipc                                                        */
4746 /*-----------------------------------------------------------------*/
4747 static void genSkipc(resolvedIfx *rifx)
4748 {
4749   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4750   
4751   if(!rifx)
4752     return;
4753
4754   if(rifx->condition)
4755     emitSKPC;
4756   else
4757     emitSKPNC;
4758
4759   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4760   rifx->generated = 1;
4761 }
4762
4763 #if !(USE_SIMPLE_GENCMP)
4764 /*-----------------------------------------------------------------*/
4765 /* genSkipz2                                                       */
4766 /*-----------------------------------------------------------------*/
4767 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4768 {
4769   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4770   
4771   if(!rifx)
4772     return;
4773
4774   if( (rifx->condition ^ invert_condition) & 1)
4775     emitSKPZ;
4776   else
4777     emitSKPNZ;
4778
4779   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4780   rifx->generated = 1;
4781 }
4782 #endif
4783
4784 #if 0
4785 /*-----------------------------------------------------------------*/
4786 /* genSkipz                                                        */
4787 /*-----------------------------------------------------------------*/
4788 static void genSkipz(iCode *ifx, int condition)
4789 {
4790   if(!ifx)
4791     return;
4792
4793   if(condition)
4794     emitSKPNZ;
4795   else
4796     emitSKPZ;
4797
4798   if ( IC_TRUE(ifx) )
4799     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4800   else
4801     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4802
4803   if ( IC_TRUE(ifx) )
4804     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4805   else
4806     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4807
4808 }
4809 #endif
4810
4811 #if !(USE_SIMPLE_GENCMP)
4812 /*-----------------------------------------------------------------*/
4813 /* genSkipCond                                                     */
4814 /*-----------------------------------------------------------------*/
4815 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4816 {
4817   if(!rifx)
4818     return;
4819
4820   if(rifx->condition)
4821     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4822   else
4823     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4824
4825
4826   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4827   rifx->generated = 1;
4828 }
4829 #endif
4830
4831 #if 0
4832 /*-----------------------------------------------------------------*/
4833 /* genChkZeroes :- greater or less than comparison                 */
4834 /*     For each byte in a literal that is zero, inclusive or the   */
4835 /*     the corresponding byte in the operand with W                */
4836 /*     returns true if any of the bytes are zero                   */
4837 /*-----------------------------------------------------------------*/
4838 static int genChkZeroes(operand *op, int lit,  int size)
4839 {
4840
4841   int i;
4842   int flag =1;
4843
4844   while(size--) {
4845     i = (lit >> (size*8)) & 0xff;
4846
4847     if(i==0) {
4848       if(flag) 
4849         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4850       else
4851         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4852       flag = 0;
4853     }
4854   }
4855
4856   return (flag==0);
4857 }
4858 #endif
4859
4860 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4861 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4862 #endif
4863 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4864 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4865
4866 /*-----------------------------------------------------------------*/
4867 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4868 /*                  aop (if it's NOT a literal) or from lit (if    */
4869 /*                  aop is a literal)                              */
4870 /*-----------------------------------------------------------------*/
4871 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4872   if (aop->type == AOP_LIT) {
4873     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4874   } else {
4875     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4876   }
4877 }
4878
4879 /*-----------------------------------------------------------------*/
4880 /* genCmp :- greater or less than comparison                       */
4881 /*-----------------------------------------------------------------*/
4882
4883 #if USE_SIMPLE_GENCMP
4884
4885 /* genCmp performs a left < right comparison, stores
4886  * the outcome in result (if != NULL) and generates
4887  * control flow code for the ifx (if != NULL).
4888  *
4889  * This version leaves in sequences like
4890  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4891  * which should be optmized by the peephole
4892  * optimizer - RN 2005-01-01 */
4893 static void genCmp (operand *left,operand *right,
4894                     operand *result, iCode *ifx, int sign)
4895 {
4896   resolvedIfx rIfx;
4897   int size;
4898   int offs;
4899   symbol *templbl;
4900   operand *dummy;
4901   unsigned long lit;
4902   unsigned long mask;
4903   int performedLt;
4904
4905   FENTRY;
4906   
4907   assert (AOP_SIZE(left) == AOP_SIZE(right));
4908   assert (left && right);
4909
4910   size = AOP_SIZE(right) - 1;
4911   mask = (0x100UL << (size*8)) - 1;
4912   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4913   performedLt = 1;
4914   templbl = NULL;
4915   lit = 0;
4916   
4917   resolveIfx (&rIfx, ifx);
4918
4919   /**********************************************************************
4920    * handle bits - bit compares are promoted to int compares seemingly! *
4921    **********************************************************************/
4922 #if 0
4923   // THIS IS COMPLETELY UNTESTED!
4924   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4925     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4926     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4927     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4928
4929     emitSETC;
4930     // 1 < {0,1} is false --> clear C by skipping the next instruction
4931     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4932     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4933     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4934     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4935     emitCLRC; // only skipped for left=0 && right=1
4936
4937     goto correct_result_in_carry;
4938   } // if
4939 #endif
4940
4941   /*************************************************
4942    * make sure that left is register (or the like) *
4943    *************************************************/
4944   if (!isAOP_REGlike(left)) {
4945     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4946     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4947     #endif
4948     assert (isAOP_LIT(left));
4949     assert (isAOP_REGlike(right));
4950     // swap left and right
4951     // left < right <==> right > left <==> (right >= left + 1)
4952     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4953
4954     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4955       // MAXVALUE < right? always false
4956       if (performedLt) emitCLRC; else emitSETC;
4957       goto correct_result_in_carry;
4958     } // if
4959
4960     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4961     // that's we handled it above.
4962     lit++;
4963
4964     dummy = left;
4965     left = right;
4966     right = dummy;
4967
4968     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4969   } else if (isAOP_LIT(right)) {
4970     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4971   } // if
4972
4973   assert (isAOP_REGlike(left)); // left must be register or the like
4974   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4975
4976   /*************************************************
4977    * special cases go here                         *
4978    *************************************************/
4979
4980   if (isAOP_LIT(right)) {
4981     if (!sign) {
4982       // unsigned comparison to a literal
4983       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4984       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4985       #endif
4986       if (lit == 0) {
4987         // unsigned left < 0? always false
4988         if (performedLt) emitCLRC; else emitSETC;
4989         goto correct_result_in_carry;
4990       }
4991     } else {
4992       // signed comparison to a literal
4993       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4994       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4995       #endif
4996       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4997         // signed left < 0x80000000? always false
4998         if (performedLt) emitCLRC; else emitSETC;
4999         goto correct_result_in_carry;
5000       } else if (lit == 0) {
5001         // compare left < 0; set CARRY if SIGNBIT(left) is set
5002         if (performedLt) emitSETC; else emitCLRC;
5003         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5004         if (performedLt) emitCLRC; else emitSETC;
5005         goto correct_result_in_carry;
5006       }
5007     } // if (!sign)
5008   } // right is literal
5009
5010   /*************************************************
5011    * perform a general case comparison             *
5012    * make sure we get CARRY==1 <==> left >= right  *
5013    *************************************************/
5014   // compare most significant bytes
5015   //DEBUGpc ("comparing bytes at offset %d", size);
5016   if (!sign) {
5017     // unsigned comparison
5018     mov2w_regOrLit (AOP(right), lit, size);
5019     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5020   } else {
5021     // signed comparison
5022     // (add 2^n to both operands then perform an unsigned comparison)
5023     if (isAOP_LIT(right)) {
5024       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5025       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5026
5027       if (litbyte == 0x80) {
5028         // left >= 0x80 -- always true, but more bytes to come
5029         pic16_mov2w (AOP(left), size);
5030         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5031         emitSETC;
5032       } else {
5033         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5034         pic16_mov2w (AOP(left), size);
5035         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5036         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5037       } // if
5038     } else {
5039       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5040       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5041       pic16_mov2w (AOP(left), size);
5042       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5043       pic16_emitpcode (POC_MOVWF, pctemp);
5044       pic16_mov2w (AOP(right), size);
5045       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5046       pic16_emitpcode (POC_SUBFW, pctemp);
5047       //pic16_popReleaseTempReg(pctemp, 1);
5048     }
5049   } // if (!sign)
5050
5051   // compare remaining bytes (treat as unsigned case from above)
5052   templbl = newiTempLabel ( NULL );
5053   offs = size;
5054   while (offs--) {
5055     //DEBUGpc ("comparing bytes at offset %d", offs);
5056     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5057     mov2w_regOrLit (AOP(right), lit, offs);
5058     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5059   } // while (offs)
5060   pic16_emitpLabel (templbl->key);
5061   goto result_in_carry;
5062
5063 result_in_carry:
5064   
5065   /****************************************************
5066    * now CARRY contains the result of the comparison: *
5067    * SUBWF sets CARRY iff                             *
5068    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5069    * (F=left, W=right)
5070    ****************************************************/
5071
5072   if (performedLt) {
5073     if (result && AOP_TYPE(result) != AOP_CRY) {
5074       // value will be stored
5075       emitTOGC;
5076     } else {
5077       // value wil only be used in the following genSkipc()
5078       rIfx.condition ^= 1;
5079     }
5080   } // if
5081
5082 correct_result_in_carry:
5083
5084   // assign result to variable (if neccessary)
5085   if (result && AOP_TYPE(result) != AOP_CRY) {
5086     //DEBUGpc ("assign result");
5087     size = AOP_SIZE(result);
5088     while (size--) {
5089       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5090     } // while
5091     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5092   } // if (result)
5093
5094   // perform conditional jump
5095   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5096   if (ifx) {
5097     //DEBUGpc ("generate control flow");
5098     rIfx.condition ^= 1;
5099     genSkipc (&rIfx);
5100     ifx->generated = 1;
5101   } // if
5102 }
5103
5104 #elif 1
5105                 /* { */
5106       /* original code */
5107 static void genCmp (operand *left,operand *right,
5108                     operand *result, iCode *ifx, int sign)
5109 {
5110   int size; //, offset = 0 ;
5111   unsigned long lit = 0L,i = 0;
5112   resolvedIfx rFalseIfx;
5113   //  resolvedIfx rTrueIfx;
5114   symbol *truelbl;
5115   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5116 /*
5117   if(ifx) {
5118     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5119     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5120   }
5121 */
5122
5123   FENTRY;
5124   
5125   resolveIfx(&rFalseIfx,ifx);
5126   truelbl  = newiTempLabel(NULL);
5127   size = max(AOP_SIZE(left),AOP_SIZE(right));
5128
5129   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5130
5131 #define _swapp
5132
5133   /* if literal is on the right then swap with left */
5134   if ((AOP_TYPE(right) == AOP_LIT)) {
5135     operand *tmp = right ;
5136     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5137     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5138 #ifdef _swapp
5139
5140     lit = (lit - 1) & mask;
5141     right = left;
5142     left = tmp;
5143     rFalseIfx.condition ^= 1;
5144 #endif
5145
5146   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5147     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5148   }
5149
5150
5151   //if(IC_TRUE(ifx) == NULL)
5152   /* if left & right are bit variables */
5153   if (AOP_TYPE(left) == AOP_CRY &&
5154       AOP_TYPE(right) == AOP_CRY ) {
5155     assert (0 && "bit variables used in genCmp");
5156     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5157     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5158   } else {
5159     /* subtract right from left if at the
5160        end the carry flag is set then we know that
5161        left is greater than right */
5162
5163     symbol *lbl  = newiTempLabel(NULL);
5164
5165 #if 0
5166         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5167                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5168 #endif
5169
5170 #ifndef _swapp
5171     if(AOP_TYPE(right) == AOP_LIT) {
5172
5173       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5174
5175       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5176
5177       /* special cases */
5178
5179       if(lit == 0) {
5180
5181         if(sign != 0) 
5182           genSkipCond(&rFalseIfx,left,size-1,7);
5183         else 
5184           /* no need to compare to 0...*/
5185           /* NOTE: this is a de-generate compare that most certainly 
5186            *       creates some dead code. */
5187           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5188
5189         if(ifx) ifx->generated = 1;
5190         return;
5191
5192       }
5193       size--;
5194
5195       if(size == 0) {
5196         //i = (lit >> (size*8)) & 0xff;
5197         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5198         
5199         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5200
5201         i = ((0-lit) & 0xff);
5202         if(sign) {
5203           if( i == 0x81) { 
5204             /* lit is 0x7f, all signed chars are less than
5205              * this except for 0x7f itself */
5206             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5207             genSkipz2(&rFalseIfx,0);
5208           } else {
5209             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5210             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5211             genSkipc(&rFalseIfx);
5212           }
5213
5214         } else {
5215           if(lit == 1) {
5216             genSkipz2(&rFalseIfx,1);
5217           } else {
5218             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5219             genSkipc(&rFalseIfx);
5220           }
5221         }
5222
5223         if(ifx) ifx->generated = 1;
5224         return;
5225       }
5226
5227       /* chars are out of the way. now do ints and longs */
5228
5229
5230       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5231         
5232       /* special cases */
5233
5234       if(sign) {
5235
5236         if(lit == 0) {
5237           genSkipCond(&rFalseIfx,left,size,7);
5238           if(ifx) ifx->generated = 1;
5239           return;
5240         }
5241
5242         if(lit <0x100) {
5243           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5244
5245           //rFalseIfx.condition ^= 1;
5246           //genSkipCond(&rFalseIfx,left,size,7);
5247           //rFalseIfx.condition ^= 1;
5248
5249           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5250           if(rFalseIfx.condition)
5251             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5252           else
5253             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5254
5255           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5256           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5257           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5258
5259           while(size > 1)
5260             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5261
5262           if(rFalseIfx.condition) {
5263             emitSKPZ;
5264             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5265
5266           } else {
5267             emitSKPNZ;
5268           }
5269
5270           genSkipc(&rFalseIfx);
5271           pic16_emitpLabel(truelbl->key);
5272           if(ifx) ifx->generated = 1;
5273           return;
5274
5275         }
5276
5277         if(size == 1) {
5278
5279           if( (lit & 0xff) == 0) {
5280             /* lower byte is zero */
5281             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5282             i = ((lit >> 8) & 0xff) ^0x80;
5283             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5284             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5285             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5286             genSkipc(&rFalseIfx);
5287
5288
5289             if(ifx) ifx->generated = 1;
5290             return;
5291
5292           }
5293         } else {
5294           /* Special cases for signed longs */
5295           if( (lit & 0xffffff) == 0) {
5296             /* lower byte is zero */
5297             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5298             i = ((lit >> 8*3) & 0xff) ^0x80;
5299             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5301             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5302             genSkipc(&rFalseIfx);
5303
5304
5305             if(ifx) ifx->generated = 1;
5306             return;
5307
5308           }
5309
5310         }
5311
5312
5313         if(lit & (0x80 << (size*8))) {
5314           /* lit is negative */
5315           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5316
5317           //genSkipCond(&rFalseIfx,left,size,7);
5318
5319           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5320
5321           if(rFalseIfx.condition)
5322             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5323           else
5324             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5325
5326
5327         } else {
5328           /* lit is positive */
5329           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331           if(rFalseIfx.condition)
5332             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5333           else
5334             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5335
5336         }
5337
5338         /*
5339           This works, but is only good for ints.
5340           It also requires a "known zero" register.
5341           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5342           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5344           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5345           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5346           genSkipc(&rFalseIfx);
5347
5348           pic16_emitpLabel(truelbl->key);
5349           if(ifx) ifx->generated = 1;
5350           return;
5351         **/
5352           
5353         /* There are no more special cases, so perform a general compare */
5354   
5355         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5356         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5357
5358         while(size--) {
5359
5360           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5361           emitSKPNZ;
5362           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5363         }
5364         //rFalseIfx.condition ^= 1;
5365         genSkipc(&rFalseIfx);
5366
5367         pic16_emitpLabel(truelbl->key);
5368
5369         if(ifx) ifx->generated = 1;
5370         return;
5371
5372
5373       }
5374
5375
5376       /* sign is out of the way. So now do an unsigned compare */
5377       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5378
5379
5380       /* General case - compare to an unsigned literal on the right.*/
5381
5382       i = (lit >> (size*8)) & 0xff;
5383       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5384       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5385       while(size--) {
5386         i = (lit >> (size*8)) & 0xff;
5387
5388         if(i) {
5389           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5390           emitSKPNZ;
5391           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5392         } else {
5393           /* this byte of the lit is zero, 
5394            *if it's not the last then OR in the variable */
5395           if(size)
5396             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5397         }
5398       }
5399
5400
5401       pic16_emitpLabel(lbl->key);
5402 //      pic16_emitpLabel(truelbl->key);
5403       //if(emitFinalCheck)
5404       genSkipc(&rFalseIfx);
5405       if(sign)
5406         pic16_emitpLabel(truelbl->key);
5407
5408       if(ifx) ifx->generated = 1;
5409       return;
5410
5411
5412     }
5413 #endif  // _swapp
5414
5415     if(AOP_TYPE(left) == AOP_LIT) {
5416       //symbol *lbl = newiTempLabel(NULL);
5417
5418       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5419
5420
5421       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5422
5423       /* Special cases */
5424       if((lit == 0) && (sign == 0)){
5425
5426         size--;
5427         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5428         while(size) 
5429           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5430
5431         genSkipz2(&rFalseIfx,0);
5432         if(ifx) ifx->generated = 1;
5433         return;
5434       }
5435
5436       if(size==1) {
5437         /* Special cases */
5438         lit &= 0xff;
5439         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5440           /* degenerate compare can never be true */
5441           if(rFalseIfx.condition == 0)
5442             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5443
5444           if(ifx) ifx->generated = 1;
5445           return;
5446         }
5447
5448         if(sign) {
5449           /* signed comparisons to a literal byte */
5450
5451           int lp1 = (lit+1) & 0xff;
5452
5453           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5454           switch (lp1) {
5455           case 0:
5456             rFalseIfx.condition ^= 1;
5457             genSkipCond(&rFalseIfx,right,0,7);
5458             break;
5459           case 0x7f:
5460             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5461             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5462             genSkipz2(&rFalseIfx,1);
5463             break;
5464           default:
5465             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5466             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5467             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5468             rFalseIfx.condition ^= 1;
5469             genSkipc(&rFalseIfx);
5470             break;
5471           }
5472         } else {
5473           /* unsigned comparisons to a literal byte */
5474
5475           switch(lit & 0xff ) {
5476           case 0:
5477             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478             genSkipz2(&rFalseIfx,0);
5479             break;
5480           case 0x7f:
5481             rFalseIfx.condition ^= 1;
5482             genSkipCond(&rFalseIfx,right,0,7);
5483             break;
5484
5485           default:
5486             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5487             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5488             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5489             rFalseIfx.condition ^= 1;
5490             if (AOP_TYPE(result) == AOP_CRY)
5491               genSkipc(&rFalseIfx);
5492             else {
5493               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5494               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5495             }         
5496             break;
5497           }
5498         }
5499
5500         if(ifx) ifx->generated = 1;
5501         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5502                 goto check_carry;
5503         return;
5504
5505       } else {
5506
5507         /* Size is greater than 1 */
5508
5509         if(sign) {
5510           int lp1 = lit+1;
5511
5512           size--;
5513
5514           if(lp1 == 0) {
5515             /* this means lit = 0xffffffff, or -1 */
5516
5517
5518             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5519             rFalseIfx.condition ^= 1;
5520             genSkipCond(&rFalseIfx,right,size,7);
5521             if(ifx) ifx->generated = 1;
5522
5523             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5524               goto check_carry;
5525
5526             return;
5527           }
5528
5529           if(lit == 0) {
5530             int s = size;
5531
5532             if(rFalseIfx.condition) {
5533               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5534               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5535             }
5536
5537             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5538             while(size--)
5539               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5540
5541
5542             emitSKPZ;
5543             if(rFalseIfx.condition) {
5544               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5545               pic16_emitpLabel(truelbl->key);
5546             }else {
5547               rFalseIfx.condition ^= 1;
5548               genSkipCond(&rFalseIfx,right,s,7);
5549             }
5550
5551             if(ifx) ifx->generated = 1;
5552
5553             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5554               goto check_carry;
5555
5556             return;
5557           }
5558
5559           if((size == 1) &&  (0 == (lp1&0xff))) {
5560             /* lower byte of signed word is zero */
5561             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5562             i = ((lp1 >> 8) & 0xff) ^0x80;
5563             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5564             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5565             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5566
5567             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5568               emitTOGC;
5569               if(ifx) ifx->generated = 1;
5570               goto check_carry;
5571             } else {
5572               rFalseIfx.condition ^= 1;
5573               genSkipc(&rFalseIfx);
5574               if(ifx) ifx->generated = 1;
5575             }
5576
5577             return;
5578           }
5579
5580           if(lit & (0x80 << (size*8))) {
5581             /* Lit is less than zero */
5582             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5583             //rFalseIfx.condition ^= 1;
5584             //genSkipCond(&rFalseIfx,left,size,7);
5585             //rFalseIfx.condition ^= 1;
5586             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5587             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5588
5589             if(rFalseIfx.condition)
5590               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5591             else
5592               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5593
5594
5595           } else {
5596             /* Lit is greater than or equal to zero */
5597             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5598             //rFalseIfx.condition ^= 1;
5599             //genSkipCond(&rFalseIfx,right,size,7);
5600             //rFalseIfx.condition ^= 1;
5601
5602             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5603             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5604
5605             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5606             if(rFalseIfx.condition)
5607               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5608             else
5609               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5610
5611           }
5612
5613           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5614           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5615
5616           while(size--) {
5617
5618             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5619             emitSKPNZ;
5620             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5621           }
5622           rFalseIfx.condition ^= 1;
5623           //rFalseIfx.condition = 1;
5624           genSkipc(&rFalseIfx);
5625
5626           pic16_emitpLabel(truelbl->key);
5627
5628           if(ifx) ifx->generated = 1;
5629
5630
5631           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5632             goto check_carry;
5633
5634           return;
5635           // end of if (sign)
5636         } else {
5637
5638           /* compare word or long to an unsigned literal on the right.*/
5639
5640
5641           size--;
5642           if(lit < 0xff) {
5643             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5644             switch (lit) {
5645             case 0:
5646               break; /* handled above */
5647 /*
5648             case 0xff:
5649               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650               while(size--)
5651                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5652               genSkipz2(&rFalseIfx,0);
5653               break;
5654 */
5655             default:
5656               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5657               while(--size)
5658                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5659
5660               emitSKPZ;
5661               if(rFalseIfx.condition)
5662                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5663               else
5664                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5665
5666
5667               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5668               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5669
5670               rFalseIfx.condition ^= 1;
5671               genSkipc(&rFalseIfx);
5672             }
5673
5674             pic16_emitpLabel(truelbl->key);
5675
5676             if(ifx) ifx->generated = 1;
5677
5678             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5679               goto check_carry;
5680
5681             return;
5682           }
5683
5684
5685           lit++;
5686           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5687           i = (lit >> (size*8)) & 0xff;
5688
5689           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5690           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5691
5692           while(size--) {
5693             i = (lit >> (size*8)) & 0xff;
5694
5695             if(i) {
5696               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5697               emitSKPNZ;
5698               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5699             } else {
5700               /* this byte of the lit is zero, 
5701                * if it's not the last then OR in the variable */
5702               if(size)
5703                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5704             }
5705           }
5706
5707
5708           pic16_emitpLabel(lbl->key);
5709
5710           rFalseIfx.condition ^= 1;
5711
5712           genSkipc(&rFalseIfx);
5713         }
5714
5715         if(sign)
5716           pic16_emitpLabel(truelbl->key);
5717         if(ifx) ifx->generated = 1;
5718
5719             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5720               goto check_carry;
5721
5722         return;
5723       }
5724     }
5725     /* Compare two variables */
5726
5727     DEBUGpic16_emitcode(";sign","%d",sign);
5728
5729     size--;
5730     if(sign) {
5731       /* Sigh. thus sucks... */
5732       if(size) {
5733         pCodeOp *pctemp;
5734         
5735         pctemp = pic16_popGetTempReg(1);
5736         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5737         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5738         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5739         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5741         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5742         pic16_popReleaseTempReg(pctemp, 1);
5743       } else {
5744         /* Signed char comparison */
5745         /* Special thanks to Nikolai Golovchenko for this snippet */
5746         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5747         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5748         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5749         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5750         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5751         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5752
5753         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5754         genSkipc(&rFalseIfx);
5755           
5756         if(ifx) ifx->generated = 1;
5757
5758             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5759               goto check_carry;
5760
5761         return;
5762       }
5763
5764     } else {
5765
5766       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5767       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5768     }
5769
5770
5771     /* The rest of the bytes of a multi-byte compare */
5772     while (size) {
5773
5774       emitSKPZ;
5775       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5776       size--;
5777
5778       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5779       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5780
5781
5782     }
5783
5784     pic16_emitpLabel(lbl->key);
5785
5786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5787     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5788         (AOP_TYPE(result) == AOP_REG)) {
5789       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5790       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5791     } else {
5792       genSkipc(&rFalseIfx);
5793     }         
5794     //genSkipc(&rFalseIfx);
5795     if(ifx) ifx->generated = 1;
5796
5797
5798             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5799               goto check_carry;
5800
5801     return;
5802
5803   }
5804
5805 check_carry:
5806   if ((AOP_TYPE(result) != AOP_CRY) 
5807         && AOP_SIZE(result)) {
5808     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5809
5810     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5811
5812     pic16_outBitC(result);
5813   } else {
5814     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5815     /* if the result is used in the next
5816        ifx conditional branch then generate
5817        code a little differently */
5818     if (ifx )
5819       genIfxJump (ifx,"c");
5820     else
5821       pic16_outBitC(result);
5822     /* leave the result in acc */
5823   }
5824
5825 }
5826
5827 #else   /* old version of genCmp() */   /* } else { */
5828
5829 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5830 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5831         operand *result, int offset, int invert_op)
5832 {
5833   /* add code here */
5834   
5835   /* check condition, > or < ?? */
5836   if(rIfx->condition != 0)invert_op ^= 1;
5837   
5838   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5839
5840   if(!ifx)invert_op ^= 1;
5841
5842   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5843       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5844   
5845   /* do selection */
5846   if(!invert_op)return POC_CPFSGT;
5847   else return POC_CPFSLT;
5848 }
5849
5850 static int compareAopfirstpass=1;
5851
5852 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5853             operand *oper, int offset, operand *result,
5854             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5855             symbol *tlbl)
5856 {
5857   int op;
5858   symbol *truelbl;
5859
5860   /* invert if there is a result to be loaded, in order to fit,
5861    * SETC/CLRC sequence */
5862   if(AOP_SIZE(result))invert_op ^= 1;
5863
5864 //  if(sign && !offset)invert_op ^= 1;
5865   
5866 //  if(sign)invert_op ^= 1;
5867   
5868   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5869
5870   if(AOP_SIZE(result) && compareAopfirstpass) {
5871     if(!ifx) {
5872       if(pcop2)
5873         pic16_emitpcode(POC_SETF, pcop2);
5874       else
5875         emitSETC;
5876     } else {
5877       if(pcop2)
5878         pic16_emitpcode(POC_CLRF, pcop2);
5879       else
5880         emitCLRC;
5881     }
5882   }
5883
5884   compareAopfirstpass = 0;
5885
5886       /* there is a bug when comparing operands with size > 1,
5887        * because higher bytes can be equal and test should be performed
5888        * to the next lower byte, current algorithm, considers operands
5889        * inequal in these cases! -- VR 20041107 */
5890
5891     
5892   if(pcop)
5893     pic16_emitpcode(op, pcop);
5894   else
5895     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5896
5897
5898   if((!sign || !offset) && AOP_SIZE(result)) {
5899     if(!ifx) {
5900       if(pcop2)
5901         pic16_emitpcode(POC_CLRF, pcop2);
5902         else
5903         emitCLRC;
5904     } else {
5905       if(pcop2)
5906         pic16_emitpcode(POC_SETF, pcop2);
5907       else
5908         emitSETC;
5909     }
5910     
5911     /* don't emit final branch (offset == 0) */
5912     if(offset) {
5913
5914       if(pcop2)
5915         pic16_emitpcode(POC_RRCF, pcop2);
5916
5917       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5918     }
5919   } else {
5920     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5921       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5922             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5923
5924       truelbl = newiTempLabel( NULL );
5925       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5926       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5927         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5928       else
5929         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5930       pic16_emitpLabel(truelbl->key);
5931     } else {
5932       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5933     }
5934   }
5935 }
5936
5937
5938   
5939
5940 #if 1   /* { */
5941 static void genCmp (operand *left, operand *right,
5942                     operand *result, iCode *ifx, int sign)
5943 {
5944   int size, cmpop=1;
5945   long lit = 0L;
5946   resolvedIfx rFalseIfx;
5947   symbol *falselbl, *tlbl;
5948
5949     FENTRY;
5950     
5951     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5952
5953     resolveIfx(&rFalseIfx, ifx);
5954     size = max(AOP_SIZE(left), AOP_SIZE(right));
5955     
5956     /* if left & right are bit variables */
5957     if(AOP_TYPE(left) == AOP_CRY
5958       && AOP_TYPE(right) == AOP_CRY ) {
5959
5960         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5961         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5962         
5963         werror(W_POSSBUG2, __FILE__, __LINE__);
5964         exit(-1);
5965     }
5966     
5967     /* if literal is on the right then swap with left */
5968     if((AOP_TYPE(right) == AOP_LIT)) {
5969       operand *tmp = right ;
5970 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5971
5972         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5973
5974 //      lit = (lit - 1) & mask;
5975         right = left;
5976         left = tmp;
5977         rFalseIfx.condition ^= 1;               /* reverse compare */
5978     } else
5979     if ((AOP_TYPE(left) == AOP_LIT)) {
5980       /* float compares are handled by support functions */
5981       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5982     }
5983
5984     /* actual comparing algorithm */
5985 //    size = AOP_SIZE( right );
5986
5987     falselbl = newiTempLabel( NULL );
5988     if(AOP_TYPE(left) == AOP_LIT) {
5989       /* compare to literal */
5990       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5991       
5992       if(sign) {
5993         pCodeOp *pct, *pct2;
5994         symbol *tlbl1;
5995
5996         /* signed compare */
5997         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5998
5999         pct = pic16_popCopyReg(&pic16_pc_prodl);
6000         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6001         tlbl = newiTempLabel( NULL );
6002         
6003         /* first compare signs:
6004          *  a. if both are positive, compare just like unsigned
6005          *  b. if both are negative, invert cmpop, compare just like unsigned
6006          *  c. if different signs, determine the result directly */
6007
6008         size--;
6009
6010 #if 1
6011         /* { */
6012         tlbl1 = newiTempLabel( NULL );
6013 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6014
6015         if(lit > 0) {
6016
6017           /* literal is zero or positive:
6018            *  a. if carry is zero, too, continue compare,
6019            *  b. if carry is set, then continue depending on cmpop ^ condition:
6020            *    1. '<' return false (literal < variable),
6021            *    2. '>' return true (literal > variable) */
6022 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6023           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6024           
6025           
6026           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6027           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6028         } else 
6029         if(lit < 0) {
6030           
6031           /* literal is negative:
6032            *  a. if carry is set, too, continue compare,
6033            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6034            *    1. '<' return true (literal < variable),
6035            *    2. '>' return false (literal > variable) */
6036 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6037           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6038           
6039           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6040           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6041         }
6042 #if 1
6043         else {
6044           /* lit == 0 */
6045           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6046           
6047           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6049         }
6050 #endif
6051         
6052         
6053         pic16_emitpLabel( tlbl1->key );
6054 #endif  /* } */
6055
6056         compareAopfirstpass=1;
6057 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6058 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6059 //        pic16_emitpcode(POC_MOVWF, pct);
6060
6061 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6062         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6063 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6064         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6065
6066         /* generic case */        
6067           while( size-- ) {
6068 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6069 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6070 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6071 //            pic16_emitpcode(POC_MOVWF, pct);
6072
6073 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6074             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6075             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6076 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6077 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6078           }
6079 //        }
6080         
6081         if(ifx)ifx->generated = 1;
6082
6083         if(AOP_SIZE(result)) {
6084           pic16_emitpLabel(tlbl->key);
6085           pic16_emitpLabel(falselbl->key);
6086           pic16_outBitOp( result, pct2 );
6087         } else {
6088           pic16_emitpLabel(tlbl->key);
6089         }
6090       } else {
6091
6092
6093         /* unsigned compare */      
6094         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6095     
6096         compareAopfirstpass=1;
6097         while(size--) {
6098           
6099           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6100           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6101
6102         }
6103
6104         if(ifx)ifx->generated = 1;
6105
6106
6107         if(AOP_SIZE(result)) {
6108           pic16_emitpLabel(falselbl->key);
6109           pic16_outBitC( result );
6110         }
6111
6112       }
6113     } else {
6114       /* compare registers */
6115       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6116
6117
6118       if(sign) {
6119         pCodeOp *pct, *pct2;
6120         
6121         /* signed compare */
6122         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6123
6124         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6125         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6126         tlbl = newiTempLabel( NULL );
6127         
6128         compareAopfirstpass=1;
6129
6130         size--;
6131         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6132 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6133         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6134         pic16_emitpcode(POC_MOVWF, pct);
6135
6136         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6137 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6138         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6139
6140         /* WREG already holds left + 0x80 */
6141         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6142         
6143         while( size-- ) {
6144           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6145 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6146           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6147           pic16_emitpcode(POC_MOVWF, pct);
6148                 
6149           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6150 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6151           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6152
6153           /* WREG already holds left + 0x80 */
6154           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6155 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6156         }
6157         
6158         if(ifx)ifx->generated = 1;
6159
6160         if(AOP_SIZE(result)) {
6161           pic16_emitpLabel(tlbl->key);
6162           pic16_emitpLabel(falselbl->key);
6163           pic16_outBitOp( result, pct2 );
6164         } else {
6165           pic16_emitpLabel(tlbl->key);
6166         }
6167
6168       } else {
6169         /* unsigned compare */      
6170         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6171
6172         compareAopfirstpass=1;
6173         while(size--) {
6174           
6175           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6176           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6177
6178         }
6179
6180         if(ifx)ifx->generated = 1;
6181         if(AOP_SIZE(result)) {
6182
6183           pic16_emitpLabel(falselbl->key);
6184           pic16_outBitC( result );
6185         }
6186
6187       }
6188     }
6189 }
6190
6191 #else    /* } else { */
6192
6193 /* new version of genCmp -- VR 20041012 */
6194 static void genCmp (operand *left,operand *right,
6195                     operand *result, iCode *ifx, int sign)
6196 {
6197   int size; //, offset = 0 ;
6198   unsigned long lit = 0L,i = 0;
6199   resolvedIfx rFalseIfx;
6200   int willCheckCarry=0;
6201   //  resolvedIfx rTrueIfx;
6202   symbol *truelbl;
6203
6204     FENTRY;
6205   
6206   /* General concept:
6207    * subtract right from left if at the end the carry flag is set then we
6208    * know that left is greater than right */
6209             
6210   resolveIfx(&rFalseIfx,ifx);
6211   truelbl  = newiTempLabel(NULL);
6212   size = max(AOP_SIZE(left),AOP_SIZE(right));
6213
6214   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6215
6216   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6217    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6218   
6219
6220   /* if literal is on the right then swap with left */
6221   if ((AOP_TYPE(right) == AOP_LIT)) {
6222     operand *tmp = right ;
6223     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6224
6225       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6226
6227 //      lit = (lit - 1) & mask;
6228       right = left;
6229       left = tmp;
6230       rFalseIfx.condition ^= 1;         /* reverse compare */
6231   } else
6232   if ((AOP_TYPE(left) == AOP_LIT)) {
6233     /* float compares are handled by support functions */
6234     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6235   }
6236
6237
6238   //if(IC_TRUE(ifx) == NULL)
6239   /* if left & right are bit variables */
6240   if (AOP_TYPE(left) == AOP_CRY &&
6241       AOP_TYPE(right) == AOP_CRY ) {
6242
6243     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6244     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6245
6246   } else {
6247     symbol *lbl  = newiTempLabel(NULL);
6248
6249     if(AOP_TYPE(left) == AOP_LIT) {
6250       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6251
6252       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6253         willCheckCarry = 1;
6254       else willCheckCarry = 0;
6255
6256       /* Special cases */
6257       if((lit == 0) && (sign == 0)) {
6258         /* unsigned compare to 0 */
6259         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6260         
6261         size--;
6262         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6263         while(size) 
6264           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6265
6266         genSkipz2(&rFalseIfx,0);
6267         if(ifx)ifx->generated = 1;
6268         return;
6269       }
6270
6271       if(size==1) {
6272         /* Special cases */
6273         lit &= 0xff;
6274         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6275           /* degenerate compare can never be true */
6276           if(rFalseIfx.condition == 0)
6277             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6278
6279           if(ifx) ifx->generated = 1;
6280           return;
6281         }
6282
6283         if(sign) {
6284           /* signed comparisons to a literal byte */
6285           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6286
6287           int lp1 = (lit+1) & 0xff;
6288
6289           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6290           switch (lp1) {
6291           case 0:
6292             rFalseIfx.condition ^= 1;
6293             genSkipCond(&rFalseIfx,right,0,7);
6294             break;
6295           case 0x7f:
6296             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6297             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6298             genSkipz2(&rFalseIfx,1);
6299             break;
6300           default:
6301             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6302             
6303             if(rFalseIfx.condition)
6304               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6305             else
6306               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6307
6308             if(willCheckCarry) {
6309               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6310               else { emitSETC; emitCLRC; }
6311               
6312             } else {
6313               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6314             }              
6315                       
6316 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6317             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6319             rFalseIfx.condition ^= 1;
6320             genSkipc(&rFalseIfx);
6321 */
6322             break;
6323           }
6324         } else {
6325           /* unsigned comparisons to a literal byte */
6326           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6327
6328           switch(lit & 0xff ) {
6329                           /* special cases */
6330           case 0:
6331             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6332             genSkipz2(&rFalseIfx,0);
6333             break;
6334           case 0x7f:
6335             rFalseIfx.condition ^= 1;
6336             genSkipCond(&rFalseIfx,right,0,7);
6337             break;
6338           default:
6339             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6340             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6341             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6342             rFalseIfx.condition ^= 1;
6343             if (AOP_TYPE(result) == AOP_CRY)
6344               genSkipc(&rFalseIfx);
6345             else {
6346               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6347               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6348             }         
6349             break;
6350           }
6351         }
6352
6353         if(ifx) ifx->generated = 1;
6354         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6355                 goto check_carry;
6356         return;
6357
6358       } else {
6359
6360         /* Size is greater than 1 */
6361
6362         if(sign) {
6363           int lp1 = lit+1;
6364
6365           size--;
6366
6367           if(lp1 == 0) {
6368             /* this means lit = 0xffffffff, or -1 */
6369
6370
6371             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6372             rFalseIfx.condition ^= 1;
6373             genSkipCond(&rFalseIfx,right,size,7);
6374             if(ifx) ifx->generated = 1;
6375             return;
6376           }
6377
6378           if(lit == 0) {
6379             int s = size;
6380
6381             if(rFalseIfx.condition) {
6382               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6383               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6384             }
6385
6386             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6387             while(size--)
6388               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6389
6390
6391             emitSKPZ;
6392             if(rFalseIfx.condition) {
6393               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6394               pic16_emitpLabel(truelbl->key);
6395             }else {
6396               rFalseIfx.condition ^= 1;
6397               genSkipCond(&rFalseIfx,right,s,7);
6398             }
6399
6400             if(ifx) ifx->generated = 1;
6401             return;
6402           }
6403
6404           if((size == 1) &&  (0 == (lp1&0xff))) {
6405             /* lower byte of signed word is zero */
6406             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6407             i = ((lp1 >> 8) & 0xff) ^0x80;
6408             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6409             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6410             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6411             rFalseIfx.condition ^= 1;
6412             genSkipc(&rFalseIfx);
6413
6414
6415             if(ifx) ifx->generated = 1;
6416             return;
6417           }
6418
6419           if(lit & (0x80 << (size*8))) {
6420             /* Lit is less than zero */
6421             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6422             //rFalseIfx.condition ^= 1;
6423             //genSkipCond(&rFalseIfx,left,size,7);
6424             //rFalseIfx.condition ^= 1;
6425             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6426             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6427
6428             if(rFalseIfx.condition)
6429               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6430             else
6431               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6432
6433
6434           } else {
6435             /* Lit is greater than or equal to zero */
6436             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6437             //rFalseIfx.condition ^= 1;
6438             //genSkipCond(&rFalseIfx,right,size,7);
6439             //rFalseIfx.condition ^= 1;
6440
6441             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6442             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6443
6444             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6445             if(rFalseIfx.condition)
6446               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6447             else
6448               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6449
6450           }
6451
6452
6453           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6454           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6455
6456           while(size--) {
6457
6458             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6459             emitSKPNZ;
6460             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6461           }
6462           rFalseIfx.condition ^= 1;
6463           //rFalseIfx.condition = 1;
6464           genSkipc(&rFalseIfx);
6465
6466           pic16_emitpLabel(truelbl->key);
6467
6468           if(ifx) ifx->generated = 1;
6469           return;
6470           // end of if (sign)
6471         } else {
6472
6473           /* compare word or long to an unsigned literal on the right.*/
6474
6475
6476           size--;
6477           if(lit < 0xff) {
6478             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6479             switch (lit) {
6480             case 0:
6481               break; /* handled above */
6482 /*
6483             case 0xff:
6484               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6485               while(size--)
6486                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6487               genSkipz2(&rFalseIfx,0);
6488               break;
6489 */
6490             default:
6491               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6492               while(--size)
6493                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6494
6495               emitSKPZ;
6496               if(rFalseIfx.condition)
6497                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6498               else
6499                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6500
6501
6502               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6503               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6504
6505               rFalseIfx.condition ^= 1;
6506               genSkipc(&rFalseIfx);
6507             }
6508
6509             pic16_emitpLabel(truelbl->key);
6510
6511             if(ifx) ifx->generated = 1;
6512             return;
6513           }
6514
6515
6516           lit++;
6517           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6518           i = (lit >> (size*8)) & 0xff;
6519
6520           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6521           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6522
6523           while(size--) {
6524             i = (lit >> (size*8)) & 0xff;
6525
6526             if(i) {
6527               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6528               emitSKPNZ;
6529               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6530             } else {
6531               /* this byte of the lit is zero, 
6532                * if it's not the last then OR in the variable */
6533               if(size)
6534                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6535             }
6536           }
6537
6538
6539           pic16_emitpLabel(lbl->key);
6540
6541           rFalseIfx.condition ^= 1;
6542
6543           genSkipc(&rFalseIfx);
6544         }
6545
6546         if(sign)
6547           pic16_emitpLabel(truelbl->key);
6548         if(ifx) ifx->generated = 1;
6549         return;
6550       }
6551     }
6552     /* Compare two variables */
6553
6554     DEBUGpic16_emitcode(";sign","%d",sign);
6555
6556     size--;
6557     if(sign) {
6558       /* Sigh. thus sucks... */
6559       if(size) {
6560         pCodeOp *pctemp;
6561         
6562         pctemp = pic16_popGetTempReg(1);
6563         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6564         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6565         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6566         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6567         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6568         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6569         pic16_popReleaseTempReg(pctemp, 1);
6570       } else {
6571         /* Signed char comparison */
6572         /* Special thanks to Nikolai Golovchenko for this snippet */
6573         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6574         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6575         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6576         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6577         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6578         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6579
6580         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6581         genSkipc(&rFalseIfx);
6582           
6583         if(ifx) ifx->generated = 1;
6584         return;
6585       }
6586
6587     } else {
6588
6589       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6590       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6591     }
6592
6593
6594     /* The rest of the bytes of a multi-byte compare */
6595     while (size) {
6596
6597       emitSKPZ;
6598       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6599       size--;
6600
6601       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6602       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6603
6604
6605     }
6606
6607     pic16_emitpLabel(lbl->key);
6608
6609     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6610     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6611         (AOP_TYPE(result) == AOP_REG)) {
6612       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6613       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6614     } else {
6615       genSkipc(&rFalseIfx);
6616     }         
6617     //genSkipc(&rFalseIfx);
6618     if(ifx) ifx->generated = 1;
6619
6620     return;
6621
6622   }
6623
6624 check_carry:
6625   if ((AOP_TYPE(result) != AOP_CRY) 
6626         && AOP_SIZE(result)) {
6627     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628
6629     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6630
6631     pic16_outBitC(result);
6632   } else {
6633     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6634     /* if the result is used in the next
6635        ifx conditional branch then generate
6636        code a little differently */
6637     if (ifx )
6638       genIfxJump (ifx,"c");
6639     else
6640       pic16_outBitC(result);
6641     /* leave the result in acc */
6642   }
6643
6644 }
6645 #endif  /* } */
6646
6647
6648 #endif  /* } */
6649
6650
6651
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpGt :- greater than comparison                             */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpGt (iCode *ic, iCode *ifx)
6656 {
6657   operand *left, *right, *result;
6658   sym_link *letype , *retype;
6659   int sign ;
6660
6661     FENTRY;
6662     
6663     left = IC_LEFT(ic);
6664     right= IC_RIGHT(ic);
6665     result = IC_RESULT(ic);
6666
6667     letype = getSpec(operandType(left));
6668     retype =getSpec(operandType(right));
6669     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6670     /* assign the amsops */
6671     pic16_aopOp (left,ic,FALSE);
6672     pic16_aopOp (right,ic,FALSE);
6673     pic16_aopOp (result,ic,TRUE);
6674
6675     genCmp(right, left, result, ifx, sign);
6676
6677     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6678     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6679     pic16_freeAsmop(result,NULL,ic,TRUE); 
6680 }
6681
6682 /*-----------------------------------------------------------------*/
6683 /* genCmpLt - less than comparisons                                */
6684 /*-----------------------------------------------------------------*/
6685 static void genCmpLt (iCode *ic, iCode *ifx)
6686 {
6687   operand *left, *right, *result;
6688   sym_link *letype , *retype;
6689   int sign ;
6690
6691     FENTRY;
6692
6693     left = IC_LEFT(ic);
6694     right= IC_RIGHT(ic);
6695     result = IC_RESULT(ic);
6696
6697     letype = getSpec(operandType(left));
6698     retype =getSpec(operandType(right));
6699     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6700
6701     /* assign the amsops */
6702     pic16_aopOp (left,ic,FALSE);
6703     pic16_aopOp (right,ic,FALSE);
6704     pic16_aopOp (result,ic,TRUE);
6705
6706     genCmp(left, right, result, ifx, sign);
6707
6708     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6709     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6710     pic16_freeAsmop(result,NULL,ic,TRUE); 
6711 }
6712
6713 #if 0
6714 // not needed ATM
6715 // FIXME reenable literal optimisation when the pic16 port is stable
6716
6717 /*-----------------------------------------------------------------*/
6718 /* genc16bit2lit - compare a 16 bit value to a literal             */
6719 /*-----------------------------------------------------------------*/
6720 static void genc16bit2lit(operand *op, int lit, int offset)
6721 {
6722   int i;
6723
6724   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6725   if( (lit&0xff) == 0) 
6726     i=1;
6727   else
6728     i=0;
6729
6730   switch( BYTEofLONG(lit,i)) { 
6731   case 0:
6732     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6733     break;
6734   case 1:
6735     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6736     break;
6737   case 0xff:
6738     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6739     break;
6740   default:
6741     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6742     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6743   }
6744
6745   i ^= 1;
6746
6747   switch( BYTEofLONG(lit,i)) { 
6748   case 0:
6749     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6750     break;
6751   case 1:
6752     emitSKPNZ;
6753     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6754     break;
6755   case 0xff:
6756     emitSKPNZ;
6757     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6758     break;
6759   default:
6760     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6761     emitSKPNZ;
6762     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6763
6764   }
6765
6766 }
6767 #endif
6768
6769 #if 0
6770 // not needed ATM
6771 /*-----------------------------------------------------------------*/
6772 /* gencjneshort - compare and jump if not equal                    */
6773 /*-----------------------------------------------------------------*/
6774 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6775 {
6776   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6777   int offset = 0;
6778   int res_offset = 0;  /* the result may be a different size then left or right */
6779   int res_size = AOP_SIZE(result);
6780   resolvedIfx rIfx;
6781   symbol *lbl, *lbl_done;
6782
6783   unsigned long lit = 0L;
6784   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6785
6786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6787   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6788   if(result)
6789     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6790   resolveIfx(&rIfx,ifx);
6791   lbl =  newiTempLabel(NULL);
6792   lbl_done =  newiTempLabel(NULL);
6793
6794
6795   /* if the left side is a literal or 
6796      if the right is in a pointer register and left 
6797      is not */
6798   if ((AOP_TYPE(left) == AOP_LIT) || 
6799       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6800     operand *t = right;
6801     right = left;
6802     left = t;
6803   }
6804   if(AOP_TYPE(right) == AOP_LIT)
6805     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6806
6807   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6808     preserve_result = 1;
6809
6810   if(result && !preserve_result)
6811     {
6812       int i;
6813       for(i = 0; i < AOP_SIZE(result); i++)
6814         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6815     }
6816
6817
6818   /* if the right side is a literal then anything goes */
6819   if (AOP_TYPE(right) == AOP_LIT &&
6820       AOP_TYPE(left) != AOP_DIR ) {
6821     switch(size) {
6822     case 2:
6823       genc16bit2lit(left, lit, 0);
6824       emitSKPZ;
6825       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6826       break;
6827     default:
6828       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6829       while (size--) {
6830         if(lit & 0xff) {
6831           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6832           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6833         } else {
6834           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6835         }
6836
6837         emitSKPZ;
6838         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6839         offset++;
6840         if(res_offset < res_size-1)
6841           res_offset++;
6842         lit >>= 8;
6843       }
6844       break;
6845     }
6846   }
6847
6848   /* if the right side is in a register or in direct space or
6849      if the left is a pointer register & right is not */    
6850   else if (AOP_TYPE(right) == AOP_REG ||
6851            AOP_TYPE(right) == AOP_DIR || 
6852            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6853            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6854     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6855     int lbl_key = lbl->key;
6856
6857     if(result) {
6858       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6859       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6860     }else {
6861       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6862       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6863               __FUNCTION__,__LINE__);
6864       return;
6865     }
6866    
6867 /*     switch(size) { */
6868 /*     case 2: */
6869 /*       genc16bit2lit(left, lit, 0); */
6870 /*       emitSKPNZ; */
6871 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6872 /*       break; */
6873 /*     default: */
6874     while (size--) {
6875       int emit_skip=1;
6876       if((AOP_TYPE(left) == AOP_DIR) && 
6877          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6878
6879         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6880         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6881
6882       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6883             
6884         switch (lit & 0xff) {
6885         case 0:
6886           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6887           break;
6888         case 1:
6889           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6890           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6891           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6892           emit_skip=0;
6893           break;
6894         case 0xff:
6895           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6896           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6897           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6898           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6899           emit_skip=0;
6900           break;
6901         default:
6902           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6903           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6904         }
6905         lit >>= 8;
6906
6907       } else {
6908         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6909       }
6910       if(emit_skip) {
6911         if(AOP_TYPE(result) == AOP_CRY) {
6912           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6913           if(rIfx.condition)
6914             emitSKPNZ;
6915           else
6916             emitSKPZ;
6917           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6918         } else {
6919           /* fix me. probably need to check result size too */
6920           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6921           if(rIfx.condition)
6922             emitSKPZ;
6923           else
6924             emitSKPNZ;
6925           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6926           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6927         }
6928         if(ifx)
6929           ifx->generated=1;
6930       }
6931       emit_skip++;
6932       offset++;
6933       if(res_offset < res_size-1)
6934         res_offset++;
6935     }
6936 /*       break; */
6937 /*     } */
6938   } else if(AOP_TYPE(right) == AOP_REG &&
6939             AOP_TYPE(left) != AOP_DIR){
6940
6941     while(size--) {
6942       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6943       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6944       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6945       if(rIfx.condition)
6946         emitSKPNZ;
6947       else
6948         emitSKPZ;
6949       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6950       offset++;
6951       if(res_offset < res_size-1)
6952         res_offset++;
6953     }
6954       
6955   }else{
6956     /* right is a pointer reg need both a & b */
6957     while(size--) {
6958       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6959       if(strcmp(l,"b"))
6960         pic16_emitcode("mov","b,%s",l);
6961       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6962       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6963       offset++;
6964     }
6965   }
6966
6967   if(result && preserve_result)
6968     {
6969       int i;
6970       for(i = 0; i < AOP_SIZE(result); i++)
6971         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6972     }
6973
6974   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6975
6976   if(result && preserve_result)
6977     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6978
6979   if(!rIfx.condition)
6980     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6981
6982   pic16_emitpLabel(lbl->key);
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       pic16_emitpLabel(lbl_done->key);
6991    }
6992
6993   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6994
6995   if(ifx)
6996     ifx->generated = 1;
6997 }
6998 #endif
6999
7000 #if 0
7001 /*-----------------------------------------------------------------*/
7002 /* gencjne - compare and jump if not equal                         */
7003 /*-----------------------------------------------------------------*/
7004 static void gencjne(operand *left, operand *right, iCode *ifx)
7005 {
7006     symbol *tlbl  = newiTempLabel(NULL);
7007
7008     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7009     gencjneshort(left, right, lbl);
7010
7011     pic16_emitcode("mov","a,%s",one);
7012     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7013     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7014     pic16_emitcode("clr","a");
7015     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7016
7017     pic16_emitpLabel(lbl->key);
7018     pic16_emitpLabel(tlbl->key);
7019
7020 }
7021 #endif
7022
7023
7024 /*-----------------------------------------------------------------*/
7025 /* is_LitOp - check if operand has to be treated as literal        */
7026 /*-----------------------------------------------------------------*/
7027 static bool is_LitOp(operand *op)
7028 {
7029   return ((AOP_TYPE(op) == AOP_LIT)
7030       || ( (AOP_TYPE(op) == AOP_PCODE)
7031           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7032               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7033 }
7034
7035 /*-----------------------------------------------------------------*/
7036 /* is_LitAOp - check if operand has to be treated as literal        */
7037 /*-----------------------------------------------------------------*/
7038 static bool is_LitAOp(asmop *aop)
7039 {
7040   return ((aop->type == AOP_LIT)
7041       || ( (aop->type == AOP_PCODE)
7042           && ( (aop->aopu.pcop->type == PO_LITERAL)
7043               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7044 }
7045
7046
7047
7048 /*-----------------------------------------------------------------*/
7049 /* genCmpEq - generates code for equal to                          */
7050 /*-----------------------------------------------------------------*/
7051 static void genCmpEq (iCode *ic, iCode *ifx)
7052 {
7053   operand *left, *right, *result;
7054   symbol *falselbl = newiTempLabel(NULL);
7055   symbol *donelbl = newiTempLabel(NULL);
7056
7057   int preserve_result = 0;
7058   int generate_result = 0;
7059   int i=0;
7060
7061   FENTRY;
7062   
7063   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7064   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7065   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7066  
7067   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7068
7069   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7070     {
7071       werror(W_POSSBUG2, __FILE__, __LINE__);
7072       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7073       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7074       goto release;
7075     }
7076
7077   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7078     {
7079       operand *tmp = right ;
7080       right = left;
7081       left = tmp;
7082     }
7083
7084   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7085     preserve_result = 1;
7086
7087   if(result && AOP_SIZE(result))
7088     generate_result = 1;
7089
7090   if(generate_result && !preserve_result)
7091     {
7092       for(i = 0; i < AOP_SIZE(result); i++)
7093         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7094     }
7095
7096   for(i=0; i < AOP_SIZE(left); i++)
7097     {
7098       if(AOP_TYPE(left) != AOP_ACC)
7099         {
7100           if(is_LitOp(left))
7101             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7102           else
7103             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7104         }
7105       if(is_LitOp(right))
7106         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7107       else
7108         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7109
7110       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7111     }
7112
7113   // result == true
7114
7115   if(generate_result && preserve_result)
7116     {
7117       for(i = 0; i < AOP_SIZE(result); i++)
7118         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7119     }
7120
7121   if(generate_result)
7122     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7123
7124   if(generate_result && preserve_result)
7125     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7126
7127   if(ifx && IC_TRUE(ifx))
7128     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7129
7130   if(ifx && IC_FALSE(ifx))
7131     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7132
7133   pic16_emitpLabel(falselbl->key);
7134
7135   // result == false
7136
7137   if(ifx && IC_FALSE(ifx))
7138     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7139
7140   if(generate_result && preserve_result)
7141     {
7142       for(i = 0; i < AOP_SIZE(result); i++)
7143         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7144     }
7145
7146   pic16_emitpLabel(donelbl->key);
7147
7148   if(ifx)
7149     ifx->generated = 1;
7150
7151 release:
7152   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7154   pic16_freeAsmop(result,NULL,ic,TRUE);
7155
7156 }
7157
7158
7159 #if 0
7160 // old version kept for reference
7161
7162 /*-----------------------------------------------------------------*/
7163 /* genCmpEq - generates code for equal to                          */
7164 /*-----------------------------------------------------------------*/
7165 static void genCmpEq (iCode *ic, iCode *ifx)
7166 {
7167     operand *left, *right, *result;
7168     unsigned long lit = 0L;
7169     int size,offset=0;
7170     symbol *falselbl  = newiTempLabel(NULL);
7171
7172
7173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7174
7175     if(ifx)
7176       DEBUGpic16_emitcode ("; ifx is non-null","");
7177     else
7178       DEBUGpic16_emitcode ("; ifx is null","");
7179
7180     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7181     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7182     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7183
7184     size = max(AOP_SIZE(left),AOP_SIZE(right));
7185
7186     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7187
7188     /* if literal, literal on the right or 
7189     if the right is in a pointer register and left 
7190     is not */
7191     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7192         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7193       operand *tmp = right ;
7194       right = left;
7195       left = tmp;
7196     }
7197
7198
7199     if(ifx && !AOP_SIZE(result)){
7200         symbol *tlbl;
7201         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7202         /* if they are both bit variables */
7203         if (AOP_TYPE(left) == AOP_CRY &&
7204             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7205                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7206             if(AOP_TYPE(right) == AOP_LIT){
7207                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7208                 if(lit == 0L){
7209                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7210                     pic16_emitcode("cpl","c");
7211                 } else if(lit == 1L) {
7212                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7213                 } else {
7214                     pic16_emitcode("clr","c");
7215                 }
7216                 /* AOP_TYPE(right) == AOP_CRY */
7217             } else {
7218                 symbol *lbl = newiTempLabel(NULL);
7219                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7220                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7221                 pic16_emitcode("cpl","c");
7222                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7223             }
7224             /* if true label then we jump if condition
7225             supplied is true */
7226             tlbl = newiTempLabel(NULL);
7227             if ( IC_TRUE(ifx) ) {
7228                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7229                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7230             } else {
7231                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7232                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7233             }
7234             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7235
7236                 {
7237                 /* left and right are both bit variables, result is carry */
7238                         resolvedIfx rIfx;
7239               
7240                         resolveIfx(&rIfx,ifx);
7241
7242                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7243                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7244                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7245                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7246                         genSkipz2(&rIfx,0);
7247                 }
7248         } else {
7249
7250                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7251
7252                         /* They're not both bit variables. Is the right a literal? */
7253                         if(AOP_TYPE(right) == AOP_LIT) {
7254                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7255             
7256                         switch(size) {
7257
7258                                 case 1:
7259                                         switch(lit & 0xff) {
7260                                                 case 1:
7261                                                                 if ( IC_TRUE(ifx) ) {
7262                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7263                                                                         emitSKPNZ;
7264                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7265                                                                 } else {
7266                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7267                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7268                                                                 }
7269                                                                 break;
7270                                                 case 0xff:
7271                                                                 if ( IC_TRUE(ifx) ) {
7272                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7273                                                                         emitSKPNZ;
7274                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7275                                                                 } else {
7276                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7277                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7278                                                                 }
7279                                                                 break;
7280                                                 default:
7281                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7282                                                                 if(lit)
7283                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7284                                                                 genSkip(ifx,'z');
7285                                         } // switch lit
7286
7287
7288                                         /* end of size == 1 */
7289                                         break;
7290               
7291                                 case 2:
7292                                         genc16bit2lit(left,lit,offset);
7293                                         genSkip(ifx,'z');
7294                                         break;
7295                                         /* end of size == 2 */
7296
7297                                 default:
7298                                         /* size is 4 */
7299                                         if(lit==0) {
7300                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7301                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7302                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7303                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7304                                                 genSkip(ifx,'z');
7305                                         } else {
7306                                                 /* search for patterns that can be optimized */
7307
7308                                                 genc16bit2lit(left,lit,0);
7309                                                 lit >>= 16;
7310                                                 if(lit) {
7311                                                                 if(IC_TRUE(ifx))
7312                                                                 emitSKPZ; // if hi word unequal
7313                                                                 else
7314                                                                 emitSKPNZ; // if hi word equal
7315                                                                 // fail early
7316                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7317                                                         genc16bit2lit(left,lit,2);
7318                                                         genSkip(ifx,'z');
7319                                                 } else {
7320                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7321                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7322                                                         genSkip(ifx,'z');
7323                                                 }
7324                                         }
7325                                                 pic16_emitpLabel(falselbl->key);
7326                                                 break;
7327
7328                         } // switch size
7329           
7330                         ifx->generated = 1;
7331                         goto release ;
7332             
7333
7334           } else if(AOP_TYPE(right) == AOP_CRY ) {
7335             /* we know the left is not a bit, but that the right is */
7336             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7337             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7338                       pic16_popGet(AOP(right),offset));
7339             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7340
7341             /* if the two are equal, then W will be 0 and the Z bit is set
7342              * we could test Z now, or go ahead and check the high order bytes if
7343              * the variable we're comparing is larger than a byte. */
7344
7345             while(--size)
7346               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7347
7348             if ( IC_TRUE(ifx) ) {
7349               emitSKPNZ;
7350               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7351               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7352             } else {
7353               emitSKPZ;
7354               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7355               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7356             }
7357
7358           } else {
7359             /* They're both variables that are larger than bits */
7360             int s = size;
7361
7362             tlbl = newiTempLabel(NULL);
7363
7364             while(size--) {
7365               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7366               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7367
7368               if ( IC_TRUE(ifx) ) {
7369                 if(size) {
7370                   emitSKPZ;
7371                 
7372                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7373
7374                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7375                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7376                 } else {
7377                   emitSKPNZ;
7378
7379                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7380
7381
7382                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7383                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7384                 }
7385               } else {
7386                 emitSKPZ;
7387
7388                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7389
7390                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7391                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7392               }
7393               offset++;
7394             }
7395             if(s>1 && IC_TRUE(ifx)) {
7396               pic16_emitpLabel(tlbl->key);
7397               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7398             }
7399           }
7400         }
7401         /* mark the icode as generated */
7402         ifx->generated = 1;
7403         goto release ;
7404     }
7405
7406     /* if they are both bit variables */
7407     if (AOP_TYPE(left) == AOP_CRY &&
7408         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7409         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7410         if(AOP_TYPE(right) == AOP_LIT){
7411             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7412             if(lit == 0L){
7413                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7414                 pic16_emitcode("cpl","c");
7415             } else if(lit == 1L) {
7416                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7417             } else {
7418                 pic16_emitcode("clr","c");
7419             }
7420             /* AOP_TYPE(right) == AOP_CRY */
7421         } else {
7422             symbol *lbl = newiTempLabel(NULL);
7423             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7424             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7425             pic16_emitcode("cpl","c");
7426             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7427         }
7428         /* c = 1 if egal */
7429         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7430             pic16_outBitC(result);
7431             goto release ;
7432         }
7433         if (ifx) {
7434             genIfxJump (ifx,"c");
7435             goto release ;
7436         }
7437         /* if the result is used in an arithmetic operation
7438         then put the result in place */
7439         pic16_outBitC(result);
7440     } else {
7441       
7442       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7443       gencjne(left,right,result,ifx);
7444 /*
7445       if(ifx) 
7446         gencjne(left,right,newiTempLabel(NULL));
7447       else {
7448         if(IC_TRUE(ifx)->key)
7449           gencjne(left,right,IC_TRUE(ifx)->key);
7450         else
7451           gencjne(left,right,IC_FALSE(ifx)->key);
7452         ifx->generated = 1;
7453         goto release ;
7454       }
7455       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7456         pic16_aopPut(AOP(result),"a",0);
7457         goto release ;
7458       }
7459
7460       if (ifx) {
7461         genIfxJump (ifx,"a");
7462         goto release ;
7463       }
7464 */
7465       /* if the result is used in an arithmetic operation
7466          then put the result in place */
7467 /*
7468       if (AOP_TYPE(result) != AOP_CRY) 
7469         pic16_outAcc(result);
7470 */
7471       /* leave the result in acc */
7472     }
7473
7474 release:
7475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477     pic16_freeAsmop(result,NULL,ic,TRUE);
7478 }
7479 #endif
7480
7481 /*-----------------------------------------------------------------*/
7482 /* ifxForOp - returns the icode containing the ifx for operand     */
7483 /*-----------------------------------------------------------------*/
7484 static iCode *ifxForOp ( operand *op, iCode *ic )
7485 {
7486   FENTRY2;
7487
7488     /* if true symbol then needs to be assigned */
7489     if (IS_TRUE_SYMOP(op))
7490         return NULL ;
7491
7492     /* if this has register type condition and
7493     the next instruction is ifx with the same operand
7494     and live to of the operand is upto the ifx only then */
7495     if (ic->next
7496         && ic->next->op == IFX
7497         && IC_COND(ic->next)->key == op->key
7498         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7499         ) {
7500                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7501           return ic->next;
7502     }
7503
7504     /*
7505     if (ic->next &&
7506         ic->next->op == IFX &&
7507         IC_COND(ic->next)->key == op->key) {
7508       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7509       return ic->next;
7510     }
7511     */
7512
7513     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7514     if (ic->next &&
7515         ic->next->op == IFX)
7516       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7517
7518     if (ic->next &&
7519         ic->next->op == IFX &&
7520         IC_COND(ic->next)->key == op->key) {
7521       DEBUGpic16_emitcode ("; "," key is okay");
7522       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7523                            OP_SYMBOL(op)->liveTo,
7524                            ic->next->seq);
7525     }
7526
7527 #if 0
7528     /* the code below is completely untested
7529      * it just allows ulong2fs.c compile -- VR */
7530          
7531     ic = ic->next;
7532     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7533                                         __FILE__, __FUNCTION__, __LINE__);
7534         
7535     /* if this has register type condition and
7536     the next instruction is ifx with the same operand
7537     and live to of the operand is upto the ifx only then */
7538     if (ic->next &&
7539         ic->next->op == IFX &&
7540         IC_COND(ic->next)->key == op->key &&
7541         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7542         return ic->next;
7543
7544     if (ic->next &&
7545         ic->next->op == IFX &&
7546         IC_COND(ic->next)->key == op->key) {
7547       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7548       return ic->next;
7549     }
7550
7551     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7552                                         __FILE__, __FUNCTION__, __LINE__);
7553
7554 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7555 #endif
7556
7557     return NULL;
7558 }
7559 /*-----------------------------------------------------------------*/
7560 /* genAndOp - for && operation                                     */
7561 /*-----------------------------------------------------------------*/
7562 static void genAndOp (iCode *ic)
7563 {
7564   operand *left,*right, *result;
7565 /*     symbol *tlbl; */
7566
7567     FENTRY;
7568
7569     /* note here that && operations that are in an
7570     if statement are taken away by backPatchLabels
7571     only those used in arthmetic operations remain */
7572     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7573     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7574     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7575
7576     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7577
7578     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7579     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7580     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7581
7582     /* if both are bit variables */
7583 /*     if (AOP_TYPE(left) == AOP_CRY && */
7584 /*         AOP_TYPE(right) == AOP_CRY ) { */
7585 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7586 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7587 /*         pic16_outBitC(result); */
7588 /*     } else { */
7589 /*         tlbl = newiTempLabel(NULL); */
7590 /*         pic16_toBoolean(left);     */
7591 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7592 /*         pic16_toBoolean(right); */
7593 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7594 /*         pic16_outBitAcc(result); */
7595 /*     } */
7596
7597     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7598     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7599     pic16_freeAsmop(result,NULL,ic,TRUE);
7600 }
7601
7602
7603 /*-----------------------------------------------------------------*/
7604 /* genOrOp - for || operation                                      */
7605 /*-----------------------------------------------------------------*/
7606 /*
7607   tsd pic port -
7608   modified this code, but it doesn't appear to ever get called
7609 */
7610
7611 static void genOrOp (iCode *ic)
7612 {
7613   operand *left,*right, *result;
7614   symbol *tlbl;
7615
7616     FENTRY;  
7617
7618   /* note here that || operations that are in an
7619     if statement are taken away by backPatchLabels
7620     only those used in arthmetic operations remain */
7621     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7622     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7623     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7624
7625     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7626
7627     /* if both are bit variables */
7628     if (AOP_TYPE(left) == AOP_CRY &&
7629         AOP_TYPE(right) == AOP_CRY ) {
7630       pic16_emitcode("clrc","");
7631       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7632                AOP(left)->aopu.aop_dir,
7633                AOP(left)->aopu.aop_dir);
7634       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7635                AOP(right)->aopu.aop_dir,
7636                AOP(right)->aopu.aop_dir);
7637       pic16_emitcode("setc","");
7638
7639     } else {
7640         tlbl = newiTempLabel(NULL);
7641         pic16_toBoolean(left);
7642         emitSKPZ;
7643         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7644         pic16_toBoolean(right);
7645         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7646
7647         pic16_outBitAcc(result);
7648     }
7649
7650     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7651     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7652     pic16_freeAsmop(result,NULL,ic,TRUE);            
7653 }
7654
7655 /*-----------------------------------------------------------------*/
7656 /* isLiteralBit - test if lit == 2^n                               */
7657 /*-----------------------------------------------------------------*/
7658 static int isLiteralBit(unsigned long lit)
7659 {
7660     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7661     0x100L,0x200L,0x400L,0x800L,
7662     0x1000L,0x2000L,0x4000L,0x8000L,
7663     0x10000L,0x20000L,0x40000L,0x80000L,
7664     0x100000L,0x200000L,0x400000L,0x800000L,
7665     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7666     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7667     int idx;
7668     
7669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7670     for(idx = 0; idx < 32; idx++)
7671         if(lit == pw[idx])
7672             return idx+1;
7673     return 0;
7674 }
7675
7676 /*-----------------------------------------------------------------*/
7677 /* continueIfTrue -                                                */
7678 /*-----------------------------------------------------------------*/
7679 static void continueIfTrue (iCode *ic)
7680 {
7681   FENTRY;
7682   if(IC_TRUE(ic))
7683     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7684   ic->generated = 1;
7685 }
7686
7687 /*-----------------------------------------------------------------*/
7688 /* jmpIfTrue -                                                     */
7689 /*-----------------------------------------------------------------*/
7690 static void jumpIfTrue (iCode *ic)
7691 {
7692   FENTRY;
7693   if(!IC_TRUE(ic))
7694     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7695   ic->generated = 1;
7696 }
7697
7698 /*-----------------------------------------------------------------*/
7699 /* jmpTrueOrFalse -                                                */
7700 /*-----------------------------------------------------------------*/
7701 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7702 {
7703   // ugly but optimized by peephole
7704   FENTRY;
7705   if(IC_TRUE(ic)){
7706     symbol *nlbl = newiTempLabel(NULL);
7707       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7708       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7709       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7710       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7711   } else {
7712     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7713     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7714   }
7715   ic->generated = 1;
7716 }
7717
7718 /*-----------------------------------------------------------------*/
7719 /* genAnd  - code for and                                          */
7720 /*-----------------------------------------------------------------*/
7721 static void genAnd (iCode *ic, iCode *ifx)
7722 {
7723   operand *left, *right, *result;
7724   int size, offset=0;  
7725   unsigned long lit = 0L;
7726   int bytelit = 0;
7727   resolvedIfx rIfx;
7728
7729     FENTRY;
7730     
7731   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7732   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7733   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7734
7735   resolveIfx(&rIfx,ifx);
7736
7737   /* if left is a literal & right is not then exchange them */
7738   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7739       AOP_NEEDSACC(left)) {
7740     operand *tmp = right ;
7741     right = left;
7742     left = tmp;
7743   }
7744
7745   /* if result = right then exchange them */
7746   if(pic16_sameRegs(AOP(result),AOP(right))){
7747     operand *tmp = right ;
7748     right = left;
7749     left = tmp;
7750   }
7751
7752   /* if right is bit then exchange them */
7753   if (AOP_TYPE(right) == AOP_CRY &&
7754       AOP_TYPE(left) != AOP_CRY){
7755     operand *tmp = right ;
7756     right = left;
7757     left = tmp;
7758   }
7759   if(AOP_TYPE(right) == AOP_LIT)
7760     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7761
7762   size = AOP_SIZE(result);
7763
7764   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7765
7766   // if(bit & yy)
7767   // result = bit & yy;
7768   if (AOP_TYPE(left) == AOP_CRY){
7769     // c = bit & literal;
7770     if(AOP_TYPE(right) == AOP_LIT){
7771       if(lit & 1) {
7772         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7773           // no change
7774           goto release;
7775         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7776       } else {
7777         // bit(result) = 0;
7778         if(size && (AOP_TYPE(result) == AOP_CRY)){
7779           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7780           goto release;
7781         }
7782         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7783           jumpIfTrue(ifx);
7784           goto release;
7785         }
7786         pic16_emitcode("clr","c");
7787       }
7788     } else {
7789       if (AOP_TYPE(right) == AOP_CRY){
7790         // c = bit & bit;
7791         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7792         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7793       } else {
7794         // c = bit & val;
7795         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7796         // c = lsb
7797         pic16_emitcode("rrc","a");
7798         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7799       }
7800     }
7801     // bit = c
7802     // val = c
7803     if(size)
7804       pic16_outBitC(result);
7805     // if(bit & ...)
7806     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7807       genIfxJump(ifx, "c");           
7808     goto release ;
7809   }
7810
7811   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7812   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7813   if((AOP_TYPE(right) == AOP_LIT) &&
7814      (AOP_TYPE(result) == AOP_CRY) &&
7815      (AOP_TYPE(left) != AOP_CRY)){
7816     int posbit = isLiteralBit(lit);
7817     /* left &  2^n */
7818     if(posbit){
7819       posbit--;
7820       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7821       // bit = left & 2^n
7822       if(size)
7823         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7824       // if(left &  2^n)
7825       else{
7826         if(ifx){
7827 /*
7828           if(IC_TRUE(ifx)) {
7829             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7830             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7831           } else {
7832             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7833             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7834           }
7835 */
7836         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7837         size = AOP_SIZE(left);
7838
7839         {
7840           int bp = posbit, ofs=0;
7841           
7842             while(bp > 7) {
7843               bp -= 8;
7844               ofs++;
7845             }
7846         
7847           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7848                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7849
7850         }
7851 /*
7852           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7853                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7854 */
7855           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7856           
7857           ifx->generated = 1;
7858         }
7859         goto release;
7860       }
7861     } else {
7862       symbol *tlbl = newiTempLabel(NULL);
7863       int sizel = AOP_SIZE(left);
7864
7865       if(size)
7866         emitSETC;
7867
7868       while(sizel--) {
7869         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7870
7871           /* patch provided by Aaron Colwell */
7872           if((posbit = isLiteralBit(bytelit)) != 0) {
7873               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7874                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7875                                                 (posbit-1),0, PO_GPR_REGISTER));
7876
7877               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7878 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7879           } else {
7880               if (bytelit == 0xff) {
7881                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7882                    * a peephole could optimize it out -- VR */
7883                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7884               } else {
7885                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7886                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7887               }
7888
7889               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7890                             pic16_popGetLabel(tlbl->key));
7891           }
7892         
7893 #if 0
7894           /* old code, left here for reference -- VR 09/2004 */
7895           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7896           // byte ==  2^n ?
7897           if((posbit = isLiteralBit(bytelit)) != 0)
7898             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7899           else{
7900             if(bytelit != 0x0FFL)
7901               pic16_emitcode("anl","a,%s",
7902                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7903             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7904           }
7905 #endif
7906         }
7907         offset++;
7908       }
7909       // bit = left & literal
7910       if(size) {
7911         emitCLRC;
7912         pic16_emitpLabel(tlbl->key);
7913       }
7914       // if(left & literal)
7915       else {
7916         if(ifx) {
7917           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7918           ifx->generated = 1;
7919         }
7920         pic16_emitpLabel(tlbl->key);
7921         goto release;
7922       }
7923     }
7924
7925     pic16_outBitC(result);
7926     goto release ;
7927   }
7928
7929   /* if left is same as result */
7930   if(pic16_sameRegs(AOP(result),AOP(left))){
7931     int know_W = -1;
7932     for(;size--; offset++,lit>>=8) {
7933       if(AOP_TYPE(right) == AOP_LIT){
7934         switch(lit & 0xff) {
7935         case 0x00:
7936           /*  and'ing with 0 has clears the result */
7937 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7938           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7939           break;
7940         case 0xff:
7941           /* and'ing with 0xff is a nop when the result and left are the same */
7942           break;
7943
7944         default:
7945           {
7946             int p = pic16_my_powof2( (~lit) & 0xff );
7947             if(p>=0) {
7948               /* only one bit is set in the literal, so use a bcf instruction */
7949 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7950               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7951
7952             } else {
7953               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7954               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7955               if(know_W != (lit&0xff))
7956                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7957               know_W = lit &0xff;
7958               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7959             }
7960           }    
7961         }
7962       } else {
7963         if (AOP_TYPE(left) == AOP_ACC) {
7964           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7965         } else {                    
7966           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7967           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7968
7969         }
7970       }
7971     }
7972
7973   } else {
7974     // left & result in different registers
7975     if(AOP_TYPE(result) == AOP_CRY){
7976       // result = bit
7977       // if(size), result in bit
7978       // if(!size && ifx), conditional oper: if(left & right)
7979       symbol *tlbl = newiTempLabel(NULL);
7980       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7981       if(size)
7982         pic16_emitcode("setb","c");
7983       while(sizer--){
7984         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7985         pic16_emitcode("anl","a,%s",
7986                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7987         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7988         offset++;
7989       }
7990       if(size){
7991         CLRC;
7992         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7993         pic16_outBitC(result);
7994       } else if(ifx)
7995         jmpTrueOrFalse(ifx, tlbl);
7996     } else {
7997       for(;(size--);offset++) {
7998         // normal case
7999         // result = left & right
8000         if(AOP_TYPE(right) == AOP_LIT){
8001           int t = (lit >> (offset*8)) & 0x0FFL;
8002           switch(t) { 
8003           case 0x00:
8004             pic16_emitcode("clrf","%s",
8005                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8006             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8007             break;
8008           case 0xff:
8009             pic16_emitcode("movf","%s,w",
8010                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011             pic16_emitcode("movwf","%s",
8012                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8013             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8014             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8015             break;
8016           default:
8017             pic16_emitcode("movlw","0x%x",t);
8018             pic16_emitcode("andwf","%s,w",
8019                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8020             pic16_emitcode("movwf","%s",
8021                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8022               
8023             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8024             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8025             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8026           }
8027           continue;
8028         }
8029
8030         if (AOP_TYPE(left) == AOP_ACC) {
8031           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8032           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8033         } else {
8034           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8035           pic16_emitcode("andwf","%s,w",
8036                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8037           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8038           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8039         }
8040         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8041         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8042       }
8043     }
8044   }
8045
8046   release :
8047     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8048   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8049   pic16_freeAsmop(result,NULL,ic,TRUE);     
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genOr  - code for or                                            */
8054 /*-----------------------------------------------------------------*/
8055 static void genOr (iCode *ic, iCode *ifx)
8056 {
8057     operand *left, *right, *result;
8058     int size, offset=0;
8059     unsigned long lit = 0L;
8060
8061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8062
8063     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8064     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8065     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8066
8067     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8068
8069     /* if left is a literal & right is not then exchange them */
8070     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8071         AOP_NEEDSACC(left)) {
8072         operand *tmp = right ;
8073         right = left;
8074         left = tmp;
8075     }
8076
8077     /* if result = right then exchange them */
8078     if(pic16_sameRegs(AOP(result),AOP(right))){
8079         operand *tmp = right ;
8080         right = left;
8081         left = tmp;
8082     }
8083
8084     /* if right is bit then exchange them */
8085     if (AOP_TYPE(right) == AOP_CRY &&
8086         AOP_TYPE(left) != AOP_CRY){
8087         operand *tmp = right ;
8088         right = left;
8089         left = tmp;
8090     }
8091
8092     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8093
8094     if(AOP_TYPE(right) == AOP_LIT)
8095         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8096
8097     size = AOP_SIZE(result);
8098
8099     // if(bit | yy)
8100     // xx = bit | yy;
8101     if (AOP_TYPE(left) == AOP_CRY){
8102         if(AOP_TYPE(right) == AOP_LIT){
8103             // c = bit & literal;
8104             if(lit){
8105                 // lit != 0 => result = 1
8106                 if(AOP_TYPE(result) == AOP_CRY){
8107                   if(size)
8108                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8109                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8110                   //     AOP(result)->aopu.aop_dir,
8111                   //     AOP(result)->aopu.aop_dir);
8112                     else if(ifx)
8113                         continueIfTrue(ifx);
8114                     goto release;
8115                 }
8116             } else {
8117                 // lit == 0 => result = left
8118                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8119                     goto release;
8120                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8121             }
8122         } else {
8123             if (AOP_TYPE(right) == AOP_CRY){
8124               if(pic16_sameRegs(AOP(result),AOP(left))){
8125                 // c = bit | bit;
8126                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8127                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8128                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8129
8130                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8131                          AOP(result)->aopu.aop_dir,
8132                          AOP(result)->aopu.aop_dir);
8133                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8134                          AOP(right)->aopu.aop_dir,
8135                          AOP(right)->aopu.aop_dir);
8136                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8137                          AOP(result)->aopu.aop_dir,
8138                          AOP(result)->aopu.aop_dir);
8139               } else {
8140                 if( AOP_TYPE(result) == AOP_ACC) {
8141                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8142                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8143                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8144                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8145
8146                 } else {
8147
8148                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8149                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8150                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8151                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8152
8153                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8154                                  AOP(result)->aopu.aop_dir,
8155                                  AOP(result)->aopu.aop_dir);
8156                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8157                                  AOP(right)->aopu.aop_dir,
8158                                  AOP(right)->aopu.aop_dir);
8159                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8160                                  AOP(left)->aopu.aop_dir,
8161                                  AOP(left)->aopu.aop_dir);
8162                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8163                                  AOP(result)->aopu.aop_dir,
8164                                  AOP(result)->aopu.aop_dir);
8165                 }
8166               }
8167             } else {
8168                 // c = bit | val;
8169                 symbol *tlbl = newiTempLabel(NULL);
8170                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8171
8172
8173                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8174                 if( AOP_TYPE(right) == AOP_ACC) {
8175                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8176                   emitSKPNZ;
8177                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8178                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8179                 }
8180
8181
8182
8183                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8184                     pic16_emitcode(";XXX setb","c");
8185                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8186                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8187                 pic16_toBoolean(right);
8188                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8189                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8190                     jmpTrueOrFalse(ifx, tlbl);
8191                     goto release;
8192                 } else {
8193                     CLRC;
8194                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8195                 }
8196             }
8197         }
8198         // bit = c
8199         // val = c
8200         if(size)
8201             pic16_outBitC(result);
8202         // if(bit | ...)
8203         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8204             genIfxJump(ifx, "c");           
8205         goto release ;
8206     }
8207
8208     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8209     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8210     if((AOP_TYPE(right) == AOP_LIT) &&
8211        (AOP_TYPE(result) == AOP_CRY) &&
8212        (AOP_TYPE(left) != AOP_CRY)){
8213         if(lit){
8214           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8215             // result = 1
8216             if(size)
8217                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8218             else 
8219                 continueIfTrue(ifx);
8220             goto release;
8221         } else {
8222           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8223             // lit = 0, result = boolean(left)
8224             if(size)
8225                 pic16_emitcode(";XXX setb","c");
8226             pic16_toBoolean(right);
8227             if(size){
8228                 symbol *tlbl = newiTempLabel(NULL);
8229                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8230                 CLRC;
8231                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8232             } else {
8233                 genIfxJump (ifx,"a");
8234                 goto release;
8235             }
8236         }
8237         pic16_outBitC(result);
8238         goto release ;
8239     }
8240
8241     /* if left is same as result */
8242     if(pic16_sameRegs(AOP(result),AOP(left))){
8243       int know_W = -1;
8244       for(;size--; offset++,lit>>=8) {
8245         if(AOP_TYPE(right) == AOP_LIT){
8246           if((lit & 0xff) == 0)
8247             /*  or'ing with 0 has no effect */
8248             continue;
8249           else {
8250             int p = pic16_my_powof2(lit & 0xff);
8251             if(p>=0) {
8252               /* only one bit is set in the literal, so use a bsf instruction */
8253               pic16_emitpcode(POC_BSF,
8254                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8255             } else {
8256               if(know_W != (lit & 0xff))
8257                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8258               know_W = lit & 0xff;
8259               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8260             }
8261                     
8262           }
8263         } else {
8264           if (AOP_TYPE(left) == AOP_ACC) {
8265             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8266             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8267           } else {                  
8268             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8269             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8270
8271             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8272             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8273
8274           }
8275         }
8276       }
8277     } else {
8278         // left & result in different registers
8279         if(AOP_TYPE(result) == AOP_CRY){
8280             // result = bit
8281             // if(size), result in bit
8282             // if(!size && ifx), conditional oper: if(left | right)
8283             symbol *tlbl = newiTempLabel(NULL);
8284             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8285             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8286
8287
8288             if(size)
8289                 pic16_emitcode(";XXX setb","c");
8290             while(sizer--){
8291                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8292                 pic16_emitcode(";XXX orl","a,%s",
8293                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8294                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8295                 offset++;
8296             }
8297             if(size){
8298                 CLRC;
8299                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8300                 pic16_outBitC(result);
8301             } else if(ifx)
8302                 jmpTrueOrFalse(ifx, tlbl);
8303         } else for(;(size--);offset++){
8304           // normal case
8305           // result = left & right
8306           if(AOP_TYPE(right) == AOP_LIT){
8307             int t = (lit >> (offset*8)) & 0x0FFL;
8308             switch(t) { 
8309             case 0x00:
8310               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8311               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8312
8313               pic16_emitcode("movf","%s,w",
8314                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8315               pic16_emitcode("movwf","%s",
8316                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8317               break;
8318             default:
8319               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8320               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8321               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8322
8323               pic16_emitcode("movlw","0x%x",t);
8324               pic16_emitcode("iorwf","%s,w",
8325                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8326               pic16_emitcode("movwf","%s",
8327                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8328               
8329             }
8330             continue;
8331           }
8332
8333           // faster than result <- left, anl result,right
8334           // and better if result is SFR
8335           if (AOP_TYPE(left) == AOP_ACC) {
8336             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8337             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8338           } else {
8339             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8340             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8341
8342             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8343             pic16_emitcode("iorwf","%s,w",
8344                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8345           }
8346           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8347           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8348         }
8349     }
8350
8351 release :
8352     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8353     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8354     pic16_freeAsmop(result,NULL,ic,TRUE);     
8355 }
8356
8357 /*-----------------------------------------------------------------*/
8358 /* genXor - code for xclusive or                                   */
8359 /*-----------------------------------------------------------------*/
8360 static void genXor (iCode *ic, iCode *ifx)
8361 {
8362   operand *left, *right, *result;
8363   int size, offset=0;
8364   unsigned long lit = 0L;
8365
8366   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8367
8368   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8369   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8370   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8371
8372   /* if left is a literal & right is not ||
8373      if left needs acc & right does not */
8374   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8375       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8376     operand *tmp = right ;
8377     right = left;
8378     left = tmp;
8379   }
8380
8381   /* if result = right then exchange them */
8382   if(pic16_sameRegs(AOP(result),AOP(right))){
8383     operand *tmp = right ;
8384     right = left;
8385     left = tmp;
8386   }
8387
8388   /* if right is bit then exchange them */
8389   if (AOP_TYPE(right) == AOP_CRY &&
8390       AOP_TYPE(left) != AOP_CRY){
8391     operand *tmp = right ;
8392     right = left;
8393     left = tmp;
8394   }
8395   if(AOP_TYPE(right) == AOP_LIT)
8396     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8397
8398   size = AOP_SIZE(result);
8399
8400   // if(bit ^ yy)
8401   // xx = bit ^ yy;
8402   if (AOP_TYPE(left) == AOP_CRY){
8403     if(AOP_TYPE(right) == AOP_LIT){
8404       // c = bit & literal;
8405       if(lit>>1){
8406         // lit>>1  != 0 => result = 1
8407         if(AOP_TYPE(result) == AOP_CRY){
8408           if(size)
8409             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8410             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8411           else if(ifx)
8412             continueIfTrue(ifx);
8413           goto release;
8414         }
8415         pic16_emitcode("setb","c");
8416       } else{
8417         // lit == (0 or 1)
8418         if(lit == 0){
8419           // lit == 0, result = left
8420           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8421             goto release;
8422           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8423         } else{
8424           // lit == 1, result = not(left)
8425           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8426             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8427             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8428             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8429             goto release;
8430           } else {
8431             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8432             pic16_emitcode("cpl","c");
8433           }
8434         }
8435       }
8436
8437     } else {
8438       // right != literal
8439       symbol *tlbl = newiTempLabel(NULL);
8440       if (AOP_TYPE(right) == AOP_CRY){
8441         // c = bit ^ bit;
8442         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8443       }
8444       else{
8445         int sizer = AOP_SIZE(right);
8446         // c = bit ^ val
8447         // if val>>1 != 0, result = 1
8448         pic16_emitcode("setb","c");
8449         while(sizer){
8450           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8451           if(sizer == 1)
8452             // test the msb of the lsb
8453             pic16_emitcode("anl","a,#0xfe");
8454           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8455           sizer--;
8456         }
8457         // val = (0,1)
8458         pic16_emitcode("rrc","a");
8459       }
8460       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8461       pic16_emitcode("cpl","c");
8462       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8463     }
8464     // bit = c
8465     // val = c
8466     if(size)
8467       pic16_outBitC(result);
8468     // if(bit | ...)
8469     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8470       genIfxJump(ifx, "c");           
8471     goto release ;
8472   }
8473
8474   if(pic16_sameRegs(AOP(result),AOP(left))){
8475     /* if left is same as result */
8476     for(;size--; offset++) {
8477       if(AOP_TYPE(right) == AOP_LIT){
8478         int t  = (lit >> (offset*8)) & 0x0FFL;
8479         if(t == 0x00L)
8480           continue;
8481         else
8482           if (IS_AOP_PREG(left)) {
8483             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8484             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8485             pic16_aopPut(AOP(result),"a",offset);
8486           } else {
8487             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8488             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8489             pic16_emitcode("xrl","%s,%s",
8490                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8491                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8492           }
8493       } else {
8494         if (AOP_TYPE(left) == AOP_ACC)
8495           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8496         else {
8497           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8498           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8499 /*
8500           if (IS_AOP_PREG(left)) {
8501             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8502             pic16_aopPut(AOP(result),"a",offset);
8503           } else
8504             pic16_emitcode("xrl","%s,a",
8505                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8506 */
8507         }
8508       }
8509     }
8510   } else {
8511     // left & result in different registers
8512     if(AOP_TYPE(result) == AOP_CRY){
8513       // result = bit
8514       // if(size), result in bit
8515       // if(!size && ifx), conditional oper: if(left ^ right)
8516       symbol *tlbl = newiTempLabel(NULL);
8517       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8518       if(size)
8519         pic16_emitcode("setb","c");
8520       while(sizer--){
8521         if((AOP_TYPE(right) == AOP_LIT) &&
8522            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8523           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8524         } else {
8525           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8526           pic16_emitcode("xrl","a,%s",
8527                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8528         }
8529         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8530         offset++;
8531       }
8532       if(size){
8533         CLRC;
8534         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8535         pic16_outBitC(result);
8536       } else if(ifx)
8537         jmpTrueOrFalse(ifx, tlbl);
8538     } else for(;(size--);offset++){
8539       // normal case
8540       // result = left & right
8541       if(AOP_TYPE(right) == AOP_LIT){
8542         int t = (lit >> (offset*8)) & 0x0FFL;
8543         switch(t) { 
8544         case 0x00:
8545           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8546           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8547           pic16_emitcode("movf","%s,w",
8548                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8549           pic16_emitcode("movwf","%s",
8550                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8551           break;
8552         case 0xff:
8553           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8554           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8555           pic16_emitcode("comf","%s,w",
8556                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8557           pic16_emitcode("movwf","%s",
8558                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8559           break;
8560         default:
8561           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8562           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8563           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8564           pic16_emitcode("movlw","0x%x",t);
8565           pic16_emitcode("xorwf","%s,w",
8566                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8567           pic16_emitcode("movwf","%s",
8568                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8569
8570         }
8571         continue;
8572       }
8573
8574       // faster than result <- left, anl result,right
8575       // and better if result is SFR
8576       if (AOP_TYPE(left) == AOP_ACC) {
8577         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8578         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8579       } else {
8580         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8581         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8582         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8583         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8584       }
8585       if ( AOP_TYPE(result) != AOP_ACC){
8586         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8587         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8588       }
8589     }
8590   }
8591
8592   release :
8593     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8594   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8595   pic16_freeAsmop(result,NULL,ic,TRUE);     
8596 }
8597
8598 /*-----------------------------------------------------------------*/
8599 /* genInline - write the inline code out                           */
8600 /*-----------------------------------------------------------------*/
8601 static void genInline (iCode *ic)
8602 {
8603   char *buffer, *bp, *bp1;
8604     
8605         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8606
8607         _G.inLine += (!options.asmpeep);
8608
8609         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8610         strcpy(buffer,IC_INLINE(ic));
8611
8612 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8613
8614         /* emit each line as a code */
8615         while (*bp) {
8616                 if (*bp == '\n') {
8617                         *bp++ = '\0';
8618
8619                         if(*bp1)
8620                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8621                         bp1 = bp;
8622                 } else {
8623                         if (*bp == ':') {
8624                                 bp++;
8625                                 *bp = '\0';
8626                                 bp++;
8627
8628                                 /* print label, use this special format with NULL directive
8629                                  * to denote that the argument should not be indented with tab */
8630                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8631                                 bp1 = bp;
8632                         } else
8633                                 bp++;
8634                 }
8635         }
8636
8637         if ((bp1 != bp) && *bp1)
8638                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8639
8640
8641     Safe_free(buffer);
8642
8643     _G.inLine -= (!options.asmpeep);
8644 }
8645
8646 /*-----------------------------------------------------------------*/
8647 /* genRRC - rotate right with carry                                */
8648 /*-----------------------------------------------------------------*/
8649 static void genRRC (iCode *ic)
8650 {
8651   operand *left , *result ;
8652   int size, offset = 0, same;
8653
8654   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8655
8656   /* rotate right with carry */
8657   left = IC_LEFT(ic);
8658   result=IC_RESULT(ic);
8659   pic16_aopOp (left,ic,FALSE);
8660   pic16_aopOp (result,ic,FALSE);
8661
8662   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8663
8664   same = pic16_sameRegs(AOP(result),AOP(left));
8665
8666   size = AOP_SIZE(result);    
8667
8668   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8669
8670   /* get the lsb and put it into the carry */
8671   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8672
8673   offset = 0 ;
8674
8675   while(size--) {
8676
8677     if(same) {
8678       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8679     } else {
8680       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8681       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8682     }
8683
8684     offset++;
8685   }
8686
8687   pic16_freeAsmop(left,NULL,ic,TRUE);
8688   pic16_freeAsmop(result,NULL,ic,TRUE);
8689 }
8690
8691 /*-----------------------------------------------------------------*/
8692 /* genRLC - generate code for rotate left with carry               */
8693 /*-----------------------------------------------------------------*/
8694 static void genRLC (iCode *ic)
8695 {    
8696   operand *left , *result ;
8697   int size, offset = 0;
8698   int same;
8699
8700   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701   /* rotate right with carry */
8702   left = IC_LEFT(ic);
8703   result=IC_RESULT(ic);
8704   pic16_aopOp (left,ic,FALSE);
8705   pic16_aopOp (result,ic,FALSE);
8706
8707   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8708
8709   same = pic16_sameRegs(AOP(result),AOP(left));
8710
8711   /* move it to the result */
8712   size = AOP_SIZE(result);    
8713
8714   /* get the msb and put it into the carry */
8715   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8716
8717   offset = 0 ;
8718
8719   while(size--) {
8720
8721     if(same) {
8722       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8723     } else {
8724       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8725       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8726     }
8727
8728     offset++;
8729   }
8730
8731
8732   pic16_freeAsmop(left,NULL,ic,TRUE);
8733   pic16_freeAsmop(result,NULL,ic,TRUE);
8734 }
8735
8736
8737 /* gpasm can get the highest order bit with HIGH/UPPER
8738  * so the following probably is not needed -- VR */
8739  
8740 /*-----------------------------------------------------------------*/
8741 /* genGetHbit - generates code get highest order bit               */
8742 /*-----------------------------------------------------------------*/
8743 static void genGetHbit (iCode *ic)
8744 {
8745     operand *left, *result;
8746     left = IC_LEFT(ic);
8747     result=IC_RESULT(ic);
8748     pic16_aopOp (left,ic,FALSE);
8749     pic16_aopOp (result,ic,FALSE);
8750
8751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8752     /* get the highest order byte into a */
8753     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8754     if(AOP_TYPE(result) == AOP_CRY){
8755         pic16_emitcode("rlc","a");
8756         pic16_outBitC(result);
8757     }
8758     else{
8759         pic16_emitcode("rl","a");
8760         pic16_emitcode("anl","a,#0x01");
8761         pic16_outAcc(result);
8762     }
8763
8764
8765     pic16_freeAsmop(left,NULL,ic,TRUE);
8766     pic16_freeAsmop(result,NULL,ic,TRUE);
8767 }
8768
8769 #if 0
8770 /*-----------------------------------------------------------------*/
8771 /* AccRol - rotate left accumulator by known count                 */
8772 /*-----------------------------------------------------------------*/
8773 static void AccRol (int shCount)
8774 {
8775     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8776     shCount &= 0x0007;              // shCount : 0..7
8777     switch(shCount){
8778         case 0 :
8779             break;
8780         case 1 :
8781             pic16_emitcode("rl","a");
8782             break;
8783         case 2 :
8784             pic16_emitcode("rl","a");
8785             pic16_emitcode("rl","a");
8786             break;
8787         case 3 :
8788             pic16_emitcode("swap","a");
8789             pic16_emitcode("rr","a");
8790             break;
8791         case 4 :
8792             pic16_emitcode("swap","a");
8793             break;
8794         case 5 :
8795             pic16_emitcode("swap","a");
8796             pic16_emitcode("rl","a");
8797             break;
8798         case 6 :
8799             pic16_emitcode("rr","a");
8800             pic16_emitcode("rr","a");
8801             break;
8802         case 7 :
8803             pic16_emitcode("rr","a");
8804             break;
8805     }
8806 }
8807 #endif
8808
8809 /*-----------------------------------------------------------------*/
8810 /* AccLsh - left shift accumulator by known count                  */
8811 /*-----------------------------------------------------------------*/
8812 static void AccLsh (int shCount)
8813 {
8814         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8815         switch(shCount){
8816                 case 0 :
8817                         return;
8818                         break;
8819                 case 1 :
8820                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8821                         break;
8822                 case 2 :
8823                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8825                         break;
8826                 case 3 :
8827                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8828                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8829                         break;
8830                 case 4 :
8831                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8832                         break;
8833                 case 5 :
8834                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8835                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8836                         break;
8837                 case 6 :
8838                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8839                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8840                         break;
8841                 case 7 :
8842                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8843                         break;
8844         }
8845
8846         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8847 }
8848
8849 /*-----------------------------------------------------------------*/
8850 /* AccRsh - right shift accumulator by known count                 */
8851 /*-----------------------------------------------------------------*/
8852 static void AccRsh (int shCount, int andmask)
8853 {
8854         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8855         switch(shCount){
8856                 case 0 :
8857                         return; break;
8858                 case 1 :
8859                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8860                         break;
8861                 case 2 :
8862                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8863                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8864                         break;
8865                 case 3 :
8866                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8867                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8868                         break;
8869                 case 4 :
8870                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8871                         break;
8872                 case 5 :
8873                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8874                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8875                         break;
8876                 case 6 :
8877                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8878                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8879                         break;
8880                 case 7 :
8881                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8882                         break;
8883         }
8884         
8885         if(andmask)
8886                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8887         else
8888                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8889 }
8890
8891 #if 0
8892 /*-----------------------------------------------------------------*/
8893 /* AccSRsh - signed right shift accumulator by known count                 */
8894 /*-----------------------------------------------------------------*/
8895 static void AccSRsh (int shCount)
8896 {
8897     symbol *tlbl ;
8898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8899     if(shCount != 0){
8900         if(shCount == 1){
8901             pic16_emitcode("mov","c,acc.7");
8902             pic16_emitcode("rrc","a");
8903         } else if(shCount == 2){
8904             pic16_emitcode("mov","c,acc.7");
8905             pic16_emitcode("rrc","a");
8906             pic16_emitcode("mov","c,acc.7");
8907             pic16_emitcode("rrc","a");
8908         } else {
8909             tlbl = newiTempLabel(NULL);
8910             /* rotate right accumulator */
8911             AccRol(8 - shCount);
8912             /* and kill the higher order bits */
8913             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8914             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8915             pic16_emitcode("orl","a,#0x%02x",
8916                      (unsigned char)~SRMask[shCount]);
8917             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8918         }
8919     }
8920 }
8921 #endif
8922
8923 /*-----------------------------------------------------------------*/
8924 /* shiftR1Left2Result - shift right one byte from left to result   */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftR1Left2ResultSigned (operand *left, int offl,
8927                                 operand *result, int offr,
8928                                 int shCount)
8929 {
8930   int same;
8931
8932   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8933
8934   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8935
8936   switch(shCount) {
8937   case 1:
8938     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8939     if(same) 
8940       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8941     else {
8942       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8943       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8944     }
8945
8946     break;
8947   case 2:
8948
8949     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8950     if(same) 
8951       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8952     else {
8953       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8955     }
8956     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8957     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8958
8959     break;
8960
8961   case 3:
8962     if(same)
8963       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8964     else {
8965       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8966       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8967     }
8968
8969     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8970     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8971     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8972
8973     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8974     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8975
8976     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8977     break;
8978
8979   case 4:
8980     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8981     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8982     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8983     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8984     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8985     break;
8986   case 5:
8987     if(same) {
8988       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8989     } else {
8990       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8991       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8992     }
8993     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8994     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8995     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8996     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8997     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8998     break;
8999
9000   case 6:
9001     if(same) {
9002       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9003       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9004       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9005       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9006       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9007       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9008     } else {
9009       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9011       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9012       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9013       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9014     }
9015     break;
9016
9017   case 7:
9018     if(same) {
9019       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9020       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9021       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023     } else {
9024       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9025       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9026       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9027     }
9028
9029   default:
9030     break;
9031   }
9032 }
9033
9034 /*-----------------------------------------------------------------*/
9035 /* shiftR1Left2Result - shift right one byte from left to result   */
9036 /*-----------------------------------------------------------------*/
9037 static void shiftR1Left2Result (operand *left, int offl,
9038                                 operand *result, int offr,
9039                                 int shCount, int sign)
9040 {
9041   int same;
9042
9043   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9044
9045   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9046
9047   /* Copy the msb into the carry if signed. */
9048   if(sign) {
9049     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9050     return;
9051   }
9052
9053
9054
9055   switch(shCount) {
9056   case 1:
9057     emitCLRC;
9058     if(same) 
9059       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9060     else {
9061       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9062       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9063     }
9064     break;
9065   case 2:
9066     emitCLRC;
9067     if(same) {
9068       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9069     } else {
9070       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9071       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9072     }
9073     emitCLRC;
9074     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9075
9076     break;
9077   case 3:
9078     if(same)
9079       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9080     else {
9081       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9082       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9083     }
9084
9085     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9086     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9087     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9088     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9089     break;
9090       
9091   case 4:
9092     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9093     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9094     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9095     break;
9096
9097   case 5:
9098     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9099     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9100     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9101     //emitCLRC;
9102     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9103
9104     break;
9105   case 6:
9106
9107     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9108     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9109     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9111     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9112     break;
9113
9114   case 7:
9115
9116     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9117     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9118     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9119
9120     break;
9121
9122   default:
9123     break;
9124   }
9125 }
9126
9127 /*-----------------------------------------------------------------*/
9128 /* shiftL1Left2Result - shift left one byte from left to result    */
9129 /*-----------------------------------------------------------------*/
9130 static void shiftL1Left2Result (operand *left, int offl,
9131                                 operand *result, int offr, int shCount)
9132 {
9133   int same;
9134
9135   //    char *l;
9136   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9137
9138   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9139   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9140     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9141     //    MOVA(l);
9142     /* shift left accumulator */
9143     //AccLsh(shCount); // don't comment out just yet...
9144   //    pic16_aopPut(AOP(result),"a",offr);
9145
9146   switch(shCount) {
9147   case 1:
9148     /* Shift left 1 bit position */
9149     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9150     if(same) {
9151       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9152     } else {
9153       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9154       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9155     }
9156     break;
9157   case 2:
9158     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9159     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9160     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9161     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9162     break;
9163   case 3:
9164     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9165     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9166     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9168     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9169     break;
9170   case 4:
9171     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9172     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9173     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174     break;
9175   case 5:
9176     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9177     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9178     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9179     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9180     break;
9181   case 6:
9182     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9183     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9184     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9185     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9186     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9187     break;
9188   case 7:
9189     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9190     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9191     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9192     break;
9193
9194   default:
9195     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9196   }
9197
9198 }
9199
9200 /*-----------------------------------------------------------------*/
9201 /* movLeft2Result - move byte from left to result                  */
9202 /*-----------------------------------------------------------------*/
9203 static void movLeft2Result (operand *left, int offl,
9204                             operand *result, int offr)
9205 {
9206   char *l;
9207   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9209     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9210
9211     if (*l == '@' && (IS_AOP_PREG(result))) {
9212       pic16_emitcode("mov","a,%s",l);
9213       pic16_aopPut(AOP(result),"a",offr);
9214     } else {
9215       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9216       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9217     }
9218   }
9219 }
9220
9221 /*-----------------------------------------------------------------*/
9222 /* shiftL2Left2Result - shift left two bytes from left to result   */
9223 /*-----------------------------------------------------------------*/
9224 static void shiftL2Left2Result (operand *left, int offl,
9225                                 operand *result, int offr, int shCount)
9226 {
9227   int same = pic16_sameRegs(AOP(result), AOP(left));
9228   int i;
9229
9230   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9231
9232   if (same && (offl != offr)) { // shift bytes
9233     if (offr > offl) {
9234        for(i=1;i>-1;i--) {
9235          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9236          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9237        }
9238     } else { // just treat as different later on
9239                 same = 0;
9240     }
9241   }
9242
9243   if(same) {
9244     switch(shCount) {
9245     case 0:
9246       break;
9247     case 1:
9248     case 2:
9249     case 3:
9250
9251       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9252       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9253       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9254
9255       while(--shCount) {
9256                 emitCLRC;
9257                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9258                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9259       }
9260
9261       break;
9262     case 4:
9263     case 5:
9264       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9265       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9266       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9267       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9268       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9269       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9270       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9271       if(shCount >=5) {
9272                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9273                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9274       }
9275       break;
9276     case 6:
9277       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9278       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9279       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9280       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9281       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9282       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9283       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9284       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9285       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9286       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9287       break;
9288     case 7:
9289       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9290       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9291       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9292       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9293       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9294     }
9295
9296   } else {
9297     switch(shCount) {
9298     case 0:
9299       break;
9300     case 1:
9301     case 2:
9302     case 3:
9303       /* note, use a mov/add for the shift since the mov has a
9304          chance of getting optimized out */
9305       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9306       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9307       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9308       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9309       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9310
9311       while(--shCount) {
9312                 emitCLRC;
9313                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9314                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9315       }
9316       break;
9317
9318     case 4:
9319     case 5:
9320       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9321       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9322       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9323       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9324       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9325       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9326       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9327       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9328
9329
9330       if(shCount == 5) {
9331                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9332                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9333       }
9334       break;
9335     case 6:
9336       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9337       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9338       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9339       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9340
9341       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9342       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9343       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9344       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9345       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9346       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9347       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9348       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9349       break;
9350     case 7:
9351       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9352       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9353       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9354       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9355       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9356     }
9357   }
9358
9359 }
9360 /*-----------------------------------------------------------------*/
9361 /* shiftR2Left2Result - shift right two bytes from left to result  */
9362 /*-----------------------------------------------------------------*/
9363 static void shiftR2Left2Result (operand *left, int offl,
9364                                 operand *result, int offr,
9365                                 int shCount, int sign)
9366 {
9367   int same = pic16_sameRegs(AOP(result), AOP(left));
9368   int i;
9369   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9370
9371   if (same && (offl != offr)) { // shift right bytes
9372     if (offr < offl) {
9373        for(i=0;i<2;i++) {
9374          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9375          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9376        }
9377     } else { // just treat as different later on
9378                 same = 0;
9379     }
9380   }
9381
9382   switch(shCount) {
9383   case 0:
9384     break;
9385   case 1:
9386   case 2:
9387   case 3:
9388     if(sign)
9389       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9390     else
9391       emitCLRC;
9392
9393     if(same) {
9394       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9395       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9396     } else {
9397       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9398       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9399       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9400       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9401     }
9402
9403     while(--shCount) {
9404       if(sign)
9405                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9406       else
9407                 emitCLRC;
9408       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9409       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9410     }
9411     break;
9412   case 4:
9413   case 5:
9414     if(same) {
9415
9416       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9417       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9418       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9419
9420       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9421       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9423       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9424     } else {
9425       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9426       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9427       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9428
9429       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9430       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9431       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9432       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9433       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9434     }
9435
9436     if(shCount >=5) {
9437       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9438       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9439     }
9440
9441     if(sign) {
9442       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9443       pic16_emitpcode(POC_BTFSC, 
9444                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9445       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9446     }
9447
9448     break;
9449
9450   case 6:
9451     if(same) {
9452
9453       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9454       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9455
9456       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9457       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9458       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9459       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9460       if(sign) {
9461         pic16_emitpcode(POC_BTFSC, 
9462                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9463         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9464       }
9465       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9466       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9467       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9468       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9469     } else {
9470       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9471       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9472       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9473       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9474       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9475       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9476       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9477       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9478       if(sign) {
9479         pic16_emitpcode(POC_BTFSC, 
9480                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9481         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9482       }
9483       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9484       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9485
9486         
9487     }
9488
9489     break;
9490   case 7:
9491     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9492     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9493     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9494     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9495     if(sign) {
9496       emitSKPNC;
9497       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9498     } else 
9499       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9500   }
9501 }
9502
9503
9504 /*-----------------------------------------------------------------*/
9505 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9506 /*-----------------------------------------------------------------*/
9507 static void shiftLLeftOrResult (operand *left, int offl,
9508                                 operand *result, int offr, int shCount)
9509 {
9510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9511
9512     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9513     /* shift left accumulator */
9514     AccLsh(shCount);
9515     /* or with result */
9516     /* back to result */
9517     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9518 }
9519
9520 /*-----------------------------------------------------------------*/
9521 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9522 /*-----------------------------------------------------------------*/
9523 static void shiftRLeftOrResult (operand *left, int offl,
9524                                 operand *result, int offr, int shCount)
9525 {
9526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9527     
9528     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9529     /* shift right accumulator */
9530     AccRsh(shCount, 1);
9531     /* or with result */
9532     /* back to result */
9533     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9534 }
9535
9536 /*-----------------------------------------------------------------*/
9537 /* genlshOne - left shift a one byte quantity by known count       */
9538 /*-----------------------------------------------------------------*/
9539 static void genlshOne (operand *result, operand *left, int shCount)
9540 {       
9541     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9542     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9543 }
9544
9545 /*-----------------------------------------------------------------*/
9546 /* genlshTwo - left shift two bytes by known amount != 0           */
9547 /*-----------------------------------------------------------------*/
9548 static void genlshTwo (operand *result,operand *left, int shCount)
9549 {
9550     int size;
9551     
9552     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9553     size = pic16_getDataSize(result);
9554
9555     /* if shCount >= 8 */
9556     if (shCount >= 8) {
9557         shCount -= 8 ;
9558
9559         if (size > 1){
9560             if (shCount)
9561                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9562             else 
9563                 movLeft2Result(left, LSB, result, MSB16);
9564         }
9565         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9566     }
9567
9568     /*  1 <= shCount <= 7 */
9569     else {  
9570         if(size == 1)
9571             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9572         else 
9573             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9574     }
9575 }
9576
9577 /*-----------------------------------------------------------------*/
9578 /* shiftLLong - shift left one long from left to result            */
9579 /* offr = LSB or MSB16                                             */
9580 /*-----------------------------------------------------------------*/
9581 static void shiftLLong (operand *left, operand *result, int offr )
9582 {
9583     int size = AOP_SIZE(result);
9584     int same = pic16_sameRegs(AOP(left),AOP(result));
9585         int i;
9586
9587     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9588
9589         if (same && (offr == MSB16)) { //shift one byte
9590                 for(i=size-1;i>=MSB16;i--) {
9591                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9592                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9593                 }
9594         } else {
9595                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9596         }
9597         
9598     if (size > LSB+offr ){
9599                 if (same) {
9600                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9601                 } else {
9602                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9603                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9604                 }
9605          }
9606
9607     if(size > MSB16+offr){
9608                 if (same) {
9609                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9610                 } else {
9611                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9612                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9613                 }
9614     }
9615
9616     if(size > MSB24+offr){
9617                 if (same) {
9618                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9619                 } else {
9620                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9621                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9622                 }
9623     }
9624
9625     if(size > MSB32+offr){
9626                 if (same) {
9627                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9628                 } else {
9629                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9630                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9631                 }
9632     }
9633     if(offr != LSB)
9634                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9635
9636 }
9637
9638 /*-----------------------------------------------------------------*/
9639 /* genlshFour - shift four byte by a known amount != 0             */
9640 /*-----------------------------------------------------------------*/
9641 static void genlshFour (operand *result, operand *left, int shCount)
9642 {
9643     int size;
9644
9645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9646     size = AOP_SIZE(result);
9647
9648     /* if shifting more that 3 bytes */
9649     if (shCount >= 24 ) {
9650         shCount -= 24;
9651         if (shCount)
9652             /* lowest order of left goes to the highest
9653             order of the destination */
9654             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9655         else
9656             movLeft2Result(left, LSB, result, MSB32);
9657
9658                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9659                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9660                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9661
9662         return;
9663     }
9664
9665     /* more than two bytes */
9666     else if ( shCount >= 16 ) {
9667         /* lower order two bytes goes to higher order two bytes */
9668         shCount -= 16;
9669         /* if some more remaining */
9670         if (shCount)
9671             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9672         else {
9673             movLeft2Result(left, MSB16, result, MSB32);
9674             movLeft2Result(left, LSB, result, MSB24);
9675         }
9676                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9677                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9678         return;
9679     }    
9680
9681     /* if more than 1 byte */
9682     else if ( shCount >= 8 ) {
9683         /* lower order three bytes goes to higher order  three bytes */
9684         shCount -= 8;
9685         if(size == 2){
9686             if(shCount)
9687                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9688             else
9689                 movLeft2Result(left, LSB, result, MSB16);
9690         }
9691         else{   /* size = 4 */
9692             if(shCount == 0){
9693                 movLeft2Result(left, MSB24, result, MSB32);
9694                 movLeft2Result(left, MSB16, result, MSB24);
9695                 movLeft2Result(left, LSB, result, MSB16);
9696                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9697             }
9698             else if(shCount == 1)
9699                 shiftLLong(left, result, MSB16);
9700             else{
9701                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9702                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9703                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9704                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9705             }
9706         }
9707     }
9708
9709     /* 1 <= shCount <= 7 */
9710     else if(shCount <= 3)
9711     { 
9712         shiftLLong(left, result, LSB);
9713         while(--shCount >= 1)
9714             shiftLLong(result, result, LSB);
9715     }
9716     /* 3 <= shCount <= 7, optimize */
9717     else{
9718         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9719         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9720         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9721     }
9722 }
9723
9724 /*-----------------------------------------------------------------*/
9725 /* genLeftShiftLiteral - left shifting by known count              */
9726 /*-----------------------------------------------------------------*/
9727 void pic16_genLeftShiftLiteral (operand *left,
9728                                  operand *right,
9729                                  operand *result,
9730                                  iCode *ic)
9731 {    
9732     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9733     int size;
9734
9735     FENTRY;
9736     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9737     pic16_freeAsmop(right,NULL,ic,TRUE);
9738
9739     pic16_aopOp(left,ic,FALSE);
9740     pic16_aopOp(result,ic,FALSE);
9741
9742     size = getSize(operandType(result));
9743
9744 #if VIEW_SIZE
9745     pic16_emitcode("; shift left ","result %d, left %d",size,
9746              AOP_SIZE(left));
9747 #endif
9748
9749     /* I suppose that the left size >= result size */
9750     if(shCount == 0){
9751         while(size--){
9752             movLeft2Result(left, size, result, size);
9753         }
9754     }
9755
9756     else if(shCount >= (size * 8))
9757         while(size--)
9758             pic16_aopPut(AOP(result),zero,size);
9759     else{
9760         switch (size) {
9761             case 1:
9762                 genlshOne (result,left,shCount);
9763                 break;
9764
9765             case 2:
9766             case 3:
9767                 genlshTwo (result,left,shCount);
9768                 break;
9769
9770             case 4:
9771                 genlshFour (result,left,shCount);
9772                 break;
9773         }
9774     }
9775     pic16_freeAsmop(left,NULL,ic,TRUE);
9776     pic16_freeAsmop(result,NULL,ic,TRUE);
9777 }
9778
9779 /*-----------------------------------------------------------------*
9780  * genMultiAsm - repeat assembly instruction for size of register.
9781  * if endian == 1, then the high byte (i.e base address + size of 
9782  * register) is used first else the low byte is used first;
9783  *-----------------------------------------------------------------*/
9784 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9785 {
9786
9787   int offset = 0;
9788
9789   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9790
9791   if(!reg)
9792     return;
9793
9794   if(!endian) {
9795     endian = 1;
9796   } else {
9797     endian = -1;
9798     offset = size-1;
9799   }
9800
9801   while(size--) {
9802     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9803     offset += endian;
9804   }
9805
9806 }
9807
9808 #if !(USE_GENERIC_SIGNED_SHIFT)
9809 /*-----------------------------------------------------------------*/
9810 /* genLeftShift - generates code for left shifting                 */
9811 /*-----------------------------------------------------------------*/
9812 static void genLeftShift (iCode *ic)
9813 {
9814   operand *left,*right, *result;
9815   int size, offset;
9816 //  char *l;
9817   symbol *tlbl , *tlbl1;
9818   pCodeOp *pctemp;
9819
9820   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9821
9822   right = IC_RIGHT(ic);
9823   left  = IC_LEFT(ic);
9824   result = IC_RESULT(ic);
9825
9826   pic16_aopOp(right,ic,FALSE);
9827
9828   /* if the shift count is known then do it 
9829      as efficiently as possible */
9830   if (AOP_TYPE(right) == AOP_LIT) {
9831     pic16_genLeftShiftLiteral (left,right,result,ic);
9832     return ;
9833   }
9834
9835   /* shift count is unknown then we have to form
9836    * a loop. Get the loop count in WREG : Note: we take
9837    * only the lower order byte since shifting
9838    * more than 32 bits make no sense anyway, ( the
9839    * largest size of an object can be only 32 bits ) */
9840   
9841   pic16_aopOp(left,ic,FALSE);
9842   pic16_aopOp(result,ic,FALSE);
9843
9844   /* now move the left to the result if they are not the
9845    * same, and if size > 1,
9846    * and if right is not same to result (!!!) -- VR */
9847   if (!pic16_sameRegs(AOP(left),AOP(result))
9848       && (AOP_SIZE(result) > 1)) {
9849
9850     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9851
9852     size = AOP_SIZE(result);
9853     offset=0;
9854     while (size--) {
9855
9856 #if 0
9857       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9858       if (*l == '@' && (IS_AOP_PREG(result))) {
9859
9860           pic16_emitcode("mov","a,%s",l);
9861           pic16_aopPut(AOP(result),"a",offset);
9862       } else
9863 #endif
9864       {
9865         /* we don't know if left is a literal or a register, take care -- VR */
9866         mov2f(AOP(result), AOP(left), offset);
9867       }
9868       offset++;
9869     }
9870   }
9871
9872   size = AOP_SIZE(result);
9873
9874   /* if it is only one byte then */
9875   if (size == 1) {
9876     if(optimized_for_speed) {
9877       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9878       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9879       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9880       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9881       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9882       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9883       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9884       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9885       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9886       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9887       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9888       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9889     } else {
9890
9891       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9892
9893       tlbl = newiTempLabel(NULL);
9894
9895 #if 1
9896       /* this is already done, why change it? */
9897       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9898                 mov2f(AOP(result), AOP(left), 0);
9899       }
9900 #endif
9901
9902       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9903       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9904       pic16_emitpLabel(tlbl->key);
9905       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9906       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9907       emitSKPC;
9908       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9909     }
9910     goto release ;
9911   }
9912     
9913   if (pic16_sameRegs(AOP(left),AOP(result))) {
9914
9915     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9916     
9917     tlbl = newiTempLabel(NULL);
9918     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9919     genMultiAsm(POC_RRCF, result, size,1);
9920     pic16_emitpLabel(tlbl->key);
9921     genMultiAsm(POC_RLCF, result, size,0);
9922     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9923     emitSKPC;
9924     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9925     goto release;
9926   }
9927
9928   //tlbl = newiTempLabel(NULL);
9929   //offset = 0 ;   
9930   //tlbl1 = newiTempLabel(NULL);
9931
9932   //reAdjustPreg(AOP(result));    
9933     
9934   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9935   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9936   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9937   //MOVA(l);
9938   //pic16_emitcode("add","a,acc");         
9939   //pic16_aopPut(AOP(result),"a",offset++);
9940   //while (--size) {
9941   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9942   //  MOVA(l);
9943   //  pic16_emitcode("rlc","a");         
9944   //  pic16_aopPut(AOP(result),"a",offset++);
9945   //}
9946   //reAdjustPreg(AOP(result));
9947
9948   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9949   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9950
9951
9952   tlbl = newiTempLabel(NULL);
9953   tlbl1= newiTempLabel(NULL);
9954
9955   size = AOP_SIZE(result);
9956   offset = 1;
9957
9958   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9959
9960   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9961
9962   /* offset should be 0, 1 or 3 */
9963   
9964   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9965   emitSKPNZ;
9966   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9967
9968   pic16_emitpcode(POC_MOVWF, pctemp);
9969
9970
9971   pic16_emitpLabel(tlbl->key);
9972
9973   emitCLRC;
9974   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9975   while(--size)
9976     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9977
9978   pic16_emitpcode(POC_DECFSZ,  pctemp);
9979   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9980   pic16_emitpLabel(tlbl1->key);
9981
9982   pic16_popReleaseTempReg(pctemp,1);
9983
9984
9985  release:
9986   pic16_freeAsmop (right,NULL,ic,TRUE);
9987   pic16_freeAsmop(left,NULL,ic,TRUE);
9988   pic16_freeAsmop(result,NULL,ic,TRUE);
9989 }
9990 #endif
9991
9992
9993 #if 0
9994 #error old code (left here for reference)
9995 /*-----------------------------------------------------------------*/
9996 /* genLeftShift - generates code for left shifting                 */
9997 /*-----------------------------------------------------------------*/
9998 static void genLeftShift (iCode *ic)
9999 {
10000   operand *left,*right, *result;
10001   int size, offset;
10002   char *l;
10003   symbol *tlbl , *tlbl1;
10004   pCodeOp *pctemp;
10005
10006   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10007
10008   right = IC_RIGHT(ic);
10009   left  = IC_LEFT(ic);
10010   result = IC_RESULT(ic);
10011
10012   pic16_aopOp(right,ic,FALSE);
10013
10014   /* if the shift count is known then do it 
10015      as efficiently as possible */
10016   if (AOP_TYPE(right) == AOP_LIT) {
10017     pic16_genLeftShiftLiteral (left,right,result,ic);
10018     return ;
10019   }
10020
10021   /* shift count is unknown then we have to form 
10022      a loop get the loop count in B : Note: we take
10023      only the lower order byte since shifting
10024      more that 32 bits make no sense anyway, ( the
10025      largest size of an object can be only 32 bits ) */  
10026
10027     
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,FALSE);
10030
10031   /* now move the left to the result if they are not the
10032      same */
10033   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10034       AOP_SIZE(result) > 1) {
10035
10036     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10037
10038     size = AOP_SIZE(result);
10039     offset=0;
10040     while (size--) {
10041       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10042       if (*l == '@' && (IS_AOP_PREG(result))) {
10043
10044         pic16_emitcode("mov","a,%s",l);
10045         pic16_aopPut(AOP(result),"a",offset);
10046       } else {
10047
10048         /* we don't know if left is a literal or a register, take care -- VR */
10049         mov2f(AOP(result), AOP(left), offset);
10050       }
10051       offset++;
10052     }
10053   }
10054
10055   size = AOP_SIZE(result);
10056
10057   /* if it is only one byte then */
10058   if (size == 1) {
10059     if(optimized_for_speed) {
10060       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10061       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10062       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10063       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10064       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10065       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10066       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10067       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10068       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10069       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10070       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10071       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10072     } else {
10073
10074       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10075
10076       tlbl = newiTempLabel(NULL);
10077       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10078                 mov2f(AOP(result), AOP(left), 0);
10079                 
10080 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10081 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10082       }
10083
10084       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10085       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10086       pic16_emitpLabel(tlbl->key);
10087       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10088       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10089       emitSKPC;
10090       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10091     }
10092     goto release ;
10093   }
10094     
10095   if (pic16_sameRegs(AOP(left),AOP(result))) {
10096
10097     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10098     
10099     tlbl = newiTempLabel(NULL);
10100     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10101     genMultiAsm(POC_RRCF, result, size,1);
10102     pic16_emitpLabel(tlbl->key);
10103     genMultiAsm(POC_RLCF, result, size,0);
10104     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10105     emitSKPC;
10106     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10107     goto release;
10108   }
10109
10110   //tlbl = newiTempLabel(NULL);
10111   //offset = 0 ;   
10112   //tlbl1 = newiTempLabel(NULL);
10113
10114   //reAdjustPreg(AOP(result));    
10115     
10116   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10117   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10118   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10119   //MOVA(l);
10120   //pic16_emitcode("add","a,acc");         
10121   //pic16_aopPut(AOP(result),"a",offset++);
10122   //while (--size) {
10123   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10124   //  MOVA(l);
10125   //  pic16_emitcode("rlc","a");         
10126   //  pic16_aopPut(AOP(result),"a",offset++);
10127   //}
10128   //reAdjustPreg(AOP(result));
10129
10130   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10131   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10132
10133
10134   tlbl = newiTempLabel(NULL);
10135   tlbl1= newiTempLabel(NULL);
10136
10137   size = AOP_SIZE(result);
10138   offset = 1;
10139
10140   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10141
10142   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10143
10144   /* offset should be 0, 1 or 3 */
10145   
10146   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10147   emitSKPNZ;
10148   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10149
10150   pic16_emitpcode(POC_MOVWF, pctemp);
10151
10152
10153   pic16_emitpLabel(tlbl->key);
10154
10155   emitCLRC;
10156   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10157   while(--size)
10158     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10159
10160   pic16_emitpcode(POC_DECFSZ,  pctemp);
10161   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10162   pic16_emitpLabel(tlbl1->key);
10163
10164   pic16_popReleaseTempReg(pctemp,1);
10165
10166
10167  release:
10168   pic16_freeAsmop (right,NULL,ic,TRUE);
10169   pic16_freeAsmop(left,NULL,ic,TRUE);
10170   pic16_freeAsmop(result,NULL,ic,TRUE);
10171 }
10172 #endif
10173
10174 /*-----------------------------------------------------------------*/
10175 /* genrshOne - right shift a one byte quantity by known count      */
10176 /*-----------------------------------------------------------------*/
10177 static void genrshOne (operand *result, operand *left,
10178                        int shCount, int sign)
10179 {
10180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10181     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genrshTwo - right shift two bytes by known amount != 0          */
10186 /*-----------------------------------------------------------------*/
10187 static void genrshTwo (operand *result,operand *left,
10188                        int shCount, int sign)
10189 {
10190   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10191   /* if shCount >= 8 */
10192   if (shCount >= 8) {
10193     shCount -= 8 ;
10194     if (shCount)
10195       shiftR1Left2Result(left, MSB16, result, LSB,
10196                          shCount, sign);
10197     else
10198       movLeft2Result(left, MSB16, result, LSB);
10199
10200     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10201
10202     if(sign) {
10203       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10204       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10205     }
10206   }
10207
10208   /*  1 <= shCount <= 7 */
10209   else
10210     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10211 }
10212
10213 /*-----------------------------------------------------------------*/
10214 /* shiftRLong - shift right one long from left to result           */
10215 /* offl = LSB or MSB16                                             */
10216 /*-----------------------------------------------------------------*/
10217 static void shiftRLong (operand *left, int offl,
10218                         operand *result, int sign)
10219 {
10220     int size = AOP_SIZE(result);
10221     int same = pic16_sameRegs(AOP(left),AOP(result));
10222     int i;
10223     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10224
10225         if (same && (offl == MSB16)) { //shift one byte right
10226                 for(i=MSB16;i<size;i++) {
10227                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10228                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10229                 }
10230         }
10231
10232     if(sign)
10233                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10234         else
10235                 emitCLRC;
10236
10237         if (same) {
10238                 if (offl == LSB)
10239                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10240         } else {
10241         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10242         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10243         }
10244
10245     if(offl == MSB16) {
10246         /* add sign of "a" */
10247         pic16_addSign(result, MSB32, sign);
10248         }
10249
10250         if (same) {
10251         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10252         } else {
10253         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10254         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10255         }
10256         
10257         if (same) {
10258         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10259         } else {
10260         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10261         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10262         }
10263
10264         if (same) {
10265         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10266         } else {
10267         if(offl == LSB){
10268                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10269                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10270         }
10271         }
10272 }
10273
10274 /*-----------------------------------------------------------------*/
10275 /* genrshFour - shift four byte by a known amount != 0             */
10276 /*-----------------------------------------------------------------*/
10277 static void genrshFour (operand *result, operand *left,
10278                         int shCount, int sign)
10279 {
10280   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10281   /* if shifting more that 3 bytes */
10282   if(shCount >= 24 ) {
10283     shCount -= 24;
10284     if(shCount)
10285       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10286     else
10287       movLeft2Result(left, MSB32, result, LSB);
10288
10289     pic16_addSign(result, MSB16, sign);
10290   }
10291   else if(shCount >= 16){
10292     shCount -= 16;
10293     if(shCount)
10294       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10295     else{
10296       movLeft2Result(left, MSB24, result, LSB);
10297       movLeft2Result(left, MSB32, result, MSB16);
10298     }
10299     pic16_addSign(result, MSB24, sign);
10300   }
10301   else if(shCount >= 8){
10302     shCount -= 8;
10303     if(shCount == 1)
10304       shiftRLong(left, MSB16, result, sign);
10305     else if(shCount == 0){
10306       movLeft2Result(left, MSB16, result, LSB);
10307       movLeft2Result(left, MSB24, result, MSB16);
10308       movLeft2Result(left, MSB32, result, MSB24);
10309       pic16_addSign(result, MSB32, sign);
10310     }
10311     else{ //shcount >= 2
10312       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10313       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10314       /* the last shift is signed */
10315       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10316       pic16_addSign(result, MSB32, sign);
10317     }
10318   }
10319   else{   /* 1 <= shCount <= 7 */
10320     if(shCount <= 2){
10321       shiftRLong(left, LSB, result, sign);
10322       if(shCount == 2)
10323         shiftRLong(result, LSB, result, sign);
10324     }
10325     else{
10326       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10327       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10328       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10329     }
10330   }
10331 }
10332
10333 /*-----------------------------------------------------------------*/
10334 /* genRightShiftLiteral - right shifting by known count            */
10335 /*-----------------------------------------------------------------*/
10336 static void genRightShiftLiteral (operand *left,
10337                                   operand *right,
10338                                   operand *result,
10339                                   iCode *ic,
10340                                   int sign)
10341 {    
10342   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10343   int lsize,res_size;
10344
10345   pic16_freeAsmop(right,NULL,ic,TRUE);
10346
10347   pic16_aopOp(left,ic,FALSE);
10348   pic16_aopOp(result,ic,FALSE);
10349
10350   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10351
10352 #if VIEW_SIZE
10353   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10354                  AOP_SIZE(left));
10355 #endif
10356
10357   lsize = pic16_getDataSize(left);
10358   res_size = pic16_getDataSize(result);
10359   /* test the LEFT size !!! */
10360
10361   /* I suppose that the left size >= result size */
10362   if(shCount == 0){
10363     while(res_size--)
10364       movLeft2Result(left, lsize, result, res_size);
10365   }
10366
10367   else if(shCount >= (lsize * 8)){
10368
10369     if(res_size == 1) {
10370       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10371       if(sign) {
10372         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10373         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10374       }
10375     } else {
10376
10377       if(sign) {
10378         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10379         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10380         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10381         while(res_size--)
10382           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10383
10384       } else {
10385
10386         while(res_size--)
10387           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10388       }
10389     }
10390   } else {
10391
10392     switch (res_size) {
10393     case 1:
10394       genrshOne (result,left,shCount,sign);
10395       break;
10396
10397     case 2:
10398       genrshTwo (result,left,shCount,sign);
10399       break;
10400
10401     case 4:
10402       genrshFour (result,left,shCount,sign);
10403       break;
10404     default :
10405       break;
10406     }
10407
10408   }
10409
10410   pic16_freeAsmop(left,NULL,ic,TRUE);
10411   pic16_freeAsmop(result,NULL,ic,TRUE);
10412 }
10413
10414 #if !(USE_GENERIC_SIGNED_SHIFT)
10415 /*-----------------------------------------------------------------*/
10416 /* genSignedRightShift - right shift of signed number              */
10417 /*-----------------------------------------------------------------*/
10418 static void genSignedRightShift (iCode *ic)
10419 {
10420   operand *right, *left, *result;
10421   int size, offset;
10422   //  char *l;
10423   symbol *tlbl, *tlbl1 ;
10424   pCodeOp *pctemp;
10425
10426   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10427
10428   /* we do it the hard way put the shift count in b
10429      and loop thru preserving the sign */
10430   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10431
10432   right = IC_RIGHT(ic);
10433   left  = IC_LEFT(ic);
10434   result = IC_RESULT(ic);
10435
10436   pic16_aopOp(right,ic,FALSE);  
10437   pic16_aopOp(left,ic,FALSE);
10438   pic16_aopOp(result,ic,FALSE);
10439
10440
10441   if ( AOP_TYPE(right) == AOP_LIT) {
10442     genRightShiftLiteral (left,right,result,ic,1);
10443     return ;
10444   }
10445   /* shift count is unknown then we have to form 
10446      a loop get the loop count in B : Note: we take
10447      only the lower order byte since shifting
10448      more that 32 bits make no sense anyway, ( the
10449      largest size of an object can be only 32 bits ) */  
10450
10451   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10452   //pic16_emitcode("inc","b");
10453   //pic16_freeAsmop (right,NULL,ic,TRUE);
10454   //pic16_aopOp(left,ic,FALSE);
10455   //pic16_aopOp(result,ic,FALSE);
10456
10457   /* now move the left to the result if they are not the
10458      same */
10459   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10460       AOP_SIZE(result) > 1) {
10461
10462     size = AOP_SIZE(result);
10463     offset=0;
10464     while (size--) { 
10465       /*
10466         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10467         if (*l == '@' && IS_AOP_PREG(result)) {
10468
10469         pic16_emitcode("mov","a,%s",l);
10470         pic16_aopPut(AOP(result),"a",offset);
10471         } else
10472         pic16_aopPut(AOP(result),l,offset);
10473       */
10474       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10475       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10476
10477       offset++;
10478     }
10479   }
10480
10481   /* mov the highest order bit to OVR */    
10482   tlbl = newiTempLabel(NULL);
10483   tlbl1= newiTempLabel(NULL);
10484
10485   size = AOP_SIZE(result);
10486   offset = size - 1;
10487
10488   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10489
10490   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10491
10492   /* offset should be 0, 1 or 3 */
10493   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10494   emitSKPNZ;
10495   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10496
10497   pic16_emitpcode(POC_MOVWF, pctemp);
10498
10499
10500   pic16_emitpLabel(tlbl->key);
10501
10502   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10503   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10504
10505   while(--size) {
10506     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10507   }
10508
10509   pic16_emitpcode(POC_DECFSZ,  pctemp);
10510   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10511   pic16_emitpLabel(tlbl1->key);
10512
10513   pic16_popReleaseTempReg(pctemp,1);
10514 #if 0
10515   size = AOP_SIZE(result);
10516   offset = size - 1;
10517   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10518   pic16_emitcode("rlc","a");
10519   pic16_emitcode("mov","ov,c");
10520   /* if it is only one byte then */
10521   if (size == 1) {
10522     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10523     MOVA(l);
10524     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10525     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10526     pic16_emitcode("mov","c,ov");
10527     pic16_emitcode("rrc","a");
10528     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10529     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10530     pic16_aopPut(AOP(result),"a",0);
10531     goto release ;
10532   }
10533
10534   reAdjustPreg(AOP(result));
10535   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10536   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10537   pic16_emitcode("mov","c,ov");
10538   while (size--) {
10539     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10540     MOVA(l);
10541     pic16_emitcode("rrc","a");         
10542     pic16_aopPut(AOP(result),"a",offset--);
10543   }
10544   reAdjustPreg(AOP(result));
10545   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10546   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10547
10548  release:
10549 #endif
10550
10551   pic16_freeAsmop(left,NULL,ic,TRUE);
10552   pic16_freeAsmop(result,NULL,ic,TRUE);
10553   pic16_freeAsmop(right,NULL,ic,TRUE);
10554 }
10555 #endif
10556
10557 #if !(USE_GENERIC_SIGNED_SHIFT)
10558 #warning This implementation of genRightShift() is incomplete!
10559 /*-----------------------------------------------------------------*/
10560 /* genRightShift - generate code for right shifting                */
10561 /*-----------------------------------------------------------------*/
10562 static void genRightShift (iCode *ic)
10563 {
10564     operand *right, *left, *result;
10565     sym_link *letype ;
10566     int size, offset;
10567     char *l;
10568     symbol *tlbl, *tlbl1 ;
10569
10570     /* if signed then we do it the hard way preserve the
10571     sign bit moving it inwards */
10572     letype = getSpec(operandType(IC_LEFT(ic)));
10573     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10574
10575     if (!SPEC_USIGN(letype)) {
10576         genSignedRightShift (ic);
10577         return ;
10578     }
10579
10580     /* signed & unsigned types are treated the same : i.e. the
10581     signed is NOT propagated inwards : quoting from the
10582     ANSI - standard : "for E1 >> E2, is equivalent to division
10583     by 2**E2 if unsigned or if it has a non-negative value,
10584     otherwise the result is implementation defined ", MY definition
10585     is that the sign does not get propagated */
10586
10587     right = IC_RIGHT(ic);
10588     left  = IC_LEFT(ic);
10589     result = IC_RESULT(ic);
10590
10591     pic16_aopOp(right,ic,FALSE);
10592
10593     /* if the shift count is known then do it 
10594     as efficiently as possible */
10595     if (AOP_TYPE(right) == AOP_LIT) {
10596         genRightShiftLiteral (left,right,result,ic, 0);
10597         return ;
10598     }
10599
10600     /* shift count is unknown then we have to form 
10601     a loop get the loop count in B : Note: we take
10602     only the lower order byte since shifting
10603     more that 32 bits make no sense anyway, ( the
10604     largest size of an object can be only 32 bits ) */  
10605
10606     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10607     pic16_emitcode("inc","b");
10608     pic16_aopOp(left,ic,FALSE);
10609     pic16_aopOp(result,ic,FALSE);
10610
10611     /* now move the left to the result if they are not the
10612     same */
10613     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10614         AOP_SIZE(result) > 1) {
10615
10616         size = AOP_SIZE(result);
10617         offset=0;
10618         while (size--) {
10619             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10620             if (*l == '@' && IS_AOP_PREG(result)) {
10621
10622                 pic16_emitcode("mov","a,%s",l);
10623                 pic16_aopPut(AOP(result),"a",offset);
10624             } else
10625                 pic16_aopPut(AOP(result),l,offset);
10626             offset++;
10627         }
10628     }
10629
10630     tlbl = newiTempLabel(NULL);
10631     tlbl1= newiTempLabel(NULL);
10632     size = AOP_SIZE(result);
10633     offset = size - 1;
10634
10635     /* if it is only one byte then */
10636     if (size == 1) {
10637
10638       tlbl = newiTempLabel(NULL);
10639       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10640         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10641         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10642       }
10643
10644       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10645       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10646       pic16_emitpLabel(tlbl->key);
10647       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10648       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10649       emitSKPC;
10650       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10651
10652       goto release ;
10653     }
10654
10655     reAdjustPreg(AOP(result));
10656     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10657     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10658     CLRC;
10659     while (size--) {
10660         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10661         MOVA(l);
10662         pic16_emitcode("rrc","a");         
10663         pic16_aopPut(AOP(result),"a",offset--);
10664     }
10665     reAdjustPreg(AOP(result));
10666
10667     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10668     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10669
10670 release:
10671     pic16_freeAsmop(left,NULL,ic,TRUE);
10672     pic16_freeAsmop (right,NULL,ic,TRUE);
10673     pic16_freeAsmop(result,NULL,ic,TRUE);
10674 }
10675 #endif
10676
10677 #if (USE_GENERIC_SIGNED_SHIFT)
10678 /*-----------------------------------------------------------------*/
10679 /* genGenericShift - generates code for left or right shifting     */
10680 /*-----------------------------------------------------------------*/
10681 static void genGenericShift (iCode *ic, int isShiftLeft) {
10682   operand *left,*right, *result;
10683   int offset;
10684   int sign, signedCount;
10685   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10686   PIC_OPCODE pos_shift, neg_shift;
10687
10688   FENTRY;
10689
10690   right = IC_RIGHT(ic);
10691   left  = IC_LEFT(ic);
10692   result = IC_RESULT(ic);
10693
10694   pic16_aopOp(right,ic,FALSE);
10695   pic16_aopOp(left,ic,FALSE);
10696   pic16_aopOp(result,ic,FALSE);
10697
10698   sign = !SPEC_USIGN(operandType (left));
10699   signedCount = !SPEC_USIGN(operandType (right));
10700
10701   /* if the shift count is known then do it 
10702      as efficiently as possible */
10703   if (AOP_TYPE(right) == AOP_LIT) {
10704     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10705     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10706     // we should modify right->aopu.aop_lit here!
10707     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10708     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10709     if (isShiftLeft)
10710       pic16_genLeftShiftLiteral (left,right,result,ic);
10711     else
10712       genRightShiftLiteral (left,right,result,ic, sign);
10713
10714     goto release;
10715   } // if (right is literal)
10716
10717   /* shift count is unknown then we have to form a loop.
10718    * Note: we take only the lower order byte since shifting
10719    * more than 32 bits make no sense anyway, ( the
10720    * largest size of an object can be only 32 bits )
10721    * Note: we perform arithmetic shifts if the left operand is
10722    * signed and we do an (effective) right shift, i. e. we
10723    * shift in the sign bit from the left. */
10724    
10725   label_complete = newiTempLabel ( NULL );
10726   label_loop_pos = newiTempLabel ( NULL );
10727   label_loop_neg = NULL;
10728   label_negative = NULL;
10729   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10730   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10731
10732   if (signedCount) {
10733     // additional labels needed
10734     label_loop_neg = newiTempLabel ( NULL );
10735     label_negative = newiTempLabel ( NULL );
10736   } // if
10737
10738   // copy source to result -- this will effectively truncate the left operand to the size of result!
10739   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10740   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10741   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10742     mov2f (AOP(result),AOP(left), offset);
10743   } // for
10744
10745   // if result is longer than left, fill with zeros (or sign)
10746   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10747     if (sign && AOP_SIZE(left) > 0) {
10748       // shift signed operand -- fill with sign
10749       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10750       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10751       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10752       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10753         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10754       } // for
10755     } else {
10756       // shift unsigned operand -- fill result with zeros
10757       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10758         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10759       } // for
10760     }
10761   } // if (size mismatch)
10762
10763   pic16_mov2w (AOP(right), 0);
10764   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10765   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10766   
10767 #if 0
10768   // perform a shift by one (shift count is positive)
10769   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10770   // 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])
10771   pic16_emitpLabel (label_loop_pos->key);
10772   emitCLRC;
10773   if (sign && (pos_shift == POC_RRCF)) {
10774     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10775     emitSETC;
10776   } // if
10777   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10778   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10779   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10780 #else
10781   // perform a shift by one (shift count is positive)
10782   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10783   // 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])
10784   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10785   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10786   emitCLRC;
10787   pic16_emitpLabel (label_loop_pos->key);
10788   if (sign && (pos_shift == POC_RRCF)) {
10789     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10790     emitSETC;
10791   } // if
10792   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10793   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10794   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10795   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10796 #endif
10797
10798   if (signedCount) {
10799     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10800
10801     pic16_emitpLabel (label_negative->key);
10802     // perform a shift by -1 (shift count is negative)
10803     // 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)
10804     emitCLRC;
10805     pic16_emitpLabel (label_loop_neg->key);
10806     if (sign && (neg_shift == POC_RRCF)) {
10807       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10808       emitSETC;
10809     } // if
10810     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10811     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10812     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10813     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10814   } // if (signedCount)
10815
10816   pic16_emitpLabel (label_complete->key);
10817
10818 release:
10819   pic16_freeAsmop (right,NULL,ic,TRUE);
10820   pic16_freeAsmop(left,NULL,ic,TRUE);
10821   pic16_freeAsmop(result,NULL,ic,TRUE);
10822 }
10823
10824 static void genLeftShift (iCode *ic) {
10825   genGenericShift (ic, 1);
10826 }
10827
10828 static void genRightShift (iCode *ic) {
10829   genGenericShift (ic, 0);
10830 }
10831 #endif
10832
10833
10834 void pic16_loadFSR0(operand *op)
10835 {
10836         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10837 }
10838
10839 /*-----------------------------------------------------------------*/
10840 /* genUnpackBits - generates code for unpacking bits               */
10841 /*-----------------------------------------------------------------*/
10842 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10843 {    
10844   int shCnt ;
10845   int rlen = 0 ;
10846   sym_link *etype, *letype;
10847   int blen=0, bstr=0;
10848   int lbstr;
10849   int offset = 0 ;
10850
10851     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10852     etype = getSpec(operandType(result));
10853     letype = getSpec(operandType(left));
10854     
10855 //    if(IS_BITFIELD(etype)) {
10856       blen = SPEC_BLEN(etype);
10857       bstr = SPEC_BSTR(etype);
10858 //    }
10859
10860     lbstr = SPEC_BSTR( letype );
10861
10862 #if 1
10863     if((blen == 1) && (bstr < 8)) {
10864       /* it is a single bit, so use the appropriate bit instructions */
10865       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10866
10867       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10868       
10869       if((ptype == POINTER) && (result)) {
10870         /* workaround to reduce the extra lfsr instruction */
10871         pic16_emitpcode(POC_BTFSC,
10872               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10873       } else {
10874         pic16_emitpcode(POC_BTFSC,
10875               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10876       }
10877         
10878       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10879
10880       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10881       return;
10882     }
10883
10884 #endif
10885
10886         /* the following call to pic16_loadFSR0 is temporary until
10887          * optimization to handle single bit assignments is added
10888          * to the function. Until then use the old safe way! -- VR */
10889         pic16_loadFSR0( left );
10890  
10891         /* read the first byte  */
10892         switch (ptype) {
10893                 case POINTER:
10894                 case IPOINTER:
10895                 case PPOINTER:
10896                 case FPOINTER:
10897                 case GPOINTER:
10898                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10899                         break;
10900                 case CPOINTER:
10901                         pic16_emitcode("clr","a");
10902                         pic16_emitcode("movc","a","@a+dptr");
10903                         break;
10904         }
10905         
10906
10907         /* if we have bitdisplacement then it fits   */
10908         /* into this byte completely or if length is */
10909         /* less than a byte                          */
10910         if ((shCnt = SPEC_BSTR(etype)) || 
10911                 (SPEC_BLEN(etype) <= 8))  {
10912
10913                 /* shift right acc */
10914                 AccRsh(shCnt, 0);
10915
10916                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10917                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10918
10919 /* VR -- normally I would use the following, but since we use the hack,
10920  * to avoid the masking from AccRsh, why not mask it right now? */
10921
10922 /*
10923                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10924 */
10925
10926                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10927           return ;
10928         }
10929
10930
10931
10932         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10933         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10934         exit(-1);
10935
10936     /* bit field did not fit in a byte  */
10937     rlen = SPEC_BLEN(etype) - 8;
10938     pic16_aopPut(AOP(result),"a",offset++);
10939
10940     while (1)  {
10941
10942         switch (ptype) {
10943         case POINTER:
10944         case IPOINTER:
10945             pic16_emitcode("inc","%s",rname);
10946             pic16_emitcode("mov","a,@%s",rname);
10947             break;
10948             
10949         case PPOINTER:
10950             pic16_emitcode("inc","%s",rname);
10951             pic16_emitcode("movx","a,@%s",rname);
10952             break;
10953
10954         case FPOINTER:
10955             pic16_emitcode("inc","dptr");
10956             pic16_emitcode("movx","a,@dptr");
10957             break;
10958             
10959         case CPOINTER:
10960             pic16_emitcode("clr","a");
10961             pic16_emitcode("inc","dptr");
10962             pic16_emitcode("movc","a","@a+dptr");
10963             break;
10964             
10965         case GPOINTER:
10966             pic16_emitcode("inc","dptr");
10967             pic16_emitcode("lcall","__gptrget");
10968             break;
10969         }
10970
10971         rlen -= 8;            
10972         /* if we are done */
10973         if ( rlen <= 0 )
10974             break ;
10975         
10976         pic16_aopPut(AOP(result),"a",offset++);
10977                               
10978     }
10979     
10980     if (rlen) {
10981         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10982         pic16_aopPut(AOP(result),"a",offset);          
10983     }
10984     
10985     return ;
10986 }
10987
10988
10989 static void genDataPointerGet(operand *left,
10990                               operand *result,
10991                               iCode *ic)
10992 {
10993   int size, offset = 0, leoffset=0 ;
10994
10995         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10996         pic16_aopOp(result, ic, FALSE);
10997
10998         size = AOP_SIZE(result);
10999 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11000
11001
11002 #if 0
11003         /* The following tests may save a redudant movff instruction when
11004          * accessing unions */
11005          
11006         /* if they are the same */
11007         if (operandsEqu (left, result)) {
11008                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11009                 goto release;
11010         }
11011 #endif
11012
11013 #if 0
11014         /* if they are the same registers */
11015         if (pic16_sameRegs(AOP(left),AOP(result))) {
11016                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11017                 goto release;
11018         }
11019 #endif
11020
11021 #if 1
11022         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11023                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11024                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11025                 goto release;
11026         }
11027 #endif
11028
11029
11030 #if 0
11031         if ( AOP_TYPE(left) == AOP_PCODE) {
11032                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11033                                 AOP(left)->aopu.pcop->name,
11034                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11035                                 PCOR(AOP(left)->aopu.pcop)->instance:
11036                                 PCOI(AOP(left)->aopu.pcop)->offset);
11037         }
11038 #endif
11039
11040         if(AOP(left)->aopu.pcop->type == PO_DIR)
11041                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11042
11043         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11044
11045         while (size--) {
11046                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11047                 
11048                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11049                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11050                         pic16_mov2w(AOP(left), offset); // patch 8
11051                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11052                 } else {
11053                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11054                                 pic16_popGet(AOP(left), offset), //patch 8
11055                                 pic16_popGet(AOP(result), offset)));
11056                 }
11057
11058                 offset++;
11059                 leoffset++;
11060         }
11061
11062 release:
11063     pic16_freeAsmop(result,NULL,ic,TRUE);
11064 }
11065
11066
11067
11068 /*-----------------------------------------------------------------*/
11069 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11070 /*-----------------------------------------------------------------*/
11071 static void genNearPointerGet (operand *left, 
11072                                operand *result, 
11073                                iCode *ic)
11074 {
11075   asmop *aop = NULL;
11076   //regs *preg = NULL ;
11077   sym_link *rtype, *retype;
11078   sym_link *ltype = operandType(left);    
11079
11080     FENTRY;
11081     
11082     rtype = operandType(result);
11083     retype= getSpec(rtype);
11084     
11085     pic16_aopOp(left,ic,FALSE);
11086
11087 //    pic16_DumpOp("(left)",left);
11088 //    pic16_DumpOp("(result)",result);
11089
11090     /* if left is rematerialisable and
11091      * result is not bit variable type and
11092      * the left is pointer to data space i.e
11093      * lower 128 bytes of space */
11094     
11095     if (AOP_TYPE(left) == AOP_PCODE
11096       && !IS_BITFIELD(retype)
11097       && DCL_TYPE(ltype) == POINTER) {
11098
11099         genDataPointerGet (left,result,ic);
11100         pic16_freeAsmop(left, NULL, ic, TRUE);
11101         return ;
11102     }
11103     
11104     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11105     pic16_aopOp (result,ic,FALSE);
11106     
11107     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11108
11109 #if 1
11110     if(IS_BITFIELD( retype )
11111       && (SPEC_BLEN(operandType(result))==1)
11112     ) {
11113       iCode *nextic;
11114       pCodeOp *jop;
11115       int bitstrt, bytestrt;
11116
11117         /* if this is bitfield of size 1, see if we are checking the value
11118          * of a single bit in an if-statement,
11119          * if yes, then don't generate usual code, but execute the
11120          * genIfx directly -- VR */
11121
11122         nextic = ic->next;
11123
11124         /* CHECK: if next iCode is IFX
11125          * and current result operand is nextic's conditional operand
11126          * and current result operand live ranges ends at nextic's key number
11127          */
11128         if((nextic->op == IFX)
11129           && (result == IC_COND(nextic))
11130           && (OP_LIVETO(result) == nextic->seq)
11131           ) {
11132             /* everything is ok then */
11133             /* find a way to optimize the genIfx iCode */
11134
11135             bytestrt = SPEC_BSTR(operandType(result))/8;
11136             bitstrt = SPEC_BSTR(operandType(result))%8;
11137             
11138             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11139
11140             genIfxpCOpJump(nextic, jop);
11141             
11142             pic16_freeAsmop(left, NULL, ic, TRUE);
11143             pic16_freeAsmop(result, NULL, ic, TRUE);
11144             return;
11145         }
11146     }
11147 #endif
11148
11149
11150     /* if the value is already in a pointer register
11151      * then don't need anything more */
11152     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11153       /* otherwise get a free pointer register */
11154       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11155                 
11156       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11157       /* bitfields will be handled by genUnpackBits */
11158       if(!IS_BITFIELD(retype)) {
11159
11160         if(is_LitAOp( AOP(left) )) {
11161           pic16_loadFSR0( left );
11162         } else {
11163             // set up FSR0 with address from left
11164             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11165             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11166         }
11167       }
11168     }
11169
11170     /* if bitfield then unpack the bits */
11171     if (IS_BITFIELD(retype)) 
11172       genUnpackBits (result, left, NULL, POINTER);
11173     else {
11174       /* we have can just get the values */
11175       int size = AOP_SIZE(result);
11176       int offset = 0;   
11177         
11178       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11179
11180       /* fsr0 is loaded already -- VR */
11181 //      pic16_loadFSR0( left );
11182
11183 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11184 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11185       while(size--) {
11186         if(size) {
11187           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11188                 pic16_popGet(AOP(result), offset++)));
11189         } else {
11190           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11191                 pic16_popGet(AOP(result), offset++)));
11192         }
11193       }
11194 #if 0
11195 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11196 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11197       if(size)
11198         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11199 #endif
11200 /*
11201         while (size--) {
11202             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11203
11204                 pic16_emitcode("mov","a,@%s",rname);
11205                 pic16_aopPut(AOP(result),"a",offset);
11206             } else {
11207                 sprintf(buffer,"@%s",rname);
11208                 pic16_aopPut(AOP(result),buffer,offset);
11209             }
11210             offset++ ;
11211             if (size)
11212                 pic16_emitcode("inc","%s",rname);
11213         }
11214 */
11215     }
11216
11217     /* now some housekeeping stuff */
11218     if (aop) {
11219       /* we had to allocate for this iCode */
11220       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11221       pic16_freeAsmop(NULL,aop,ic,TRUE);
11222     } else { 
11223       /* we did not allocate which means left
11224        * already in a pointer register, then
11225        * if size > 0 && this could be used again
11226        * we have to point it back to where it 
11227        * belongs */
11228       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11229       if (AOP_SIZE(result) > 1
11230         && !OP_SYMBOL(left)->remat
11231         && ( OP_SYMBOL(left)->liveTo > ic->seq
11232             || ic->depth )) {
11233 //        int size = AOP_SIZE(result) - 1;
11234 //        while (size--)
11235 //          pic16_emitcode("dec","%s",rname);
11236         }
11237     }
11238
11239     /* done */
11240     pic16_freeAsmop(left,NULL,ic,TRUE);
11241     pic16_freeAsmop(result,NULL,ic,TRUE);
11242 }
11243
11244 /*-----------------------------------------------------------------*/
11245 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11246 /*-----------------------------------------------------------------*/
11247 static void genPagedPointerGet (operand *left, 
11248                                operand *result, 
11249                                iCode *ic)
11250 {
11251     asmop *aop = NULL;
11252     regs *preg = NULL ;
11253     char *rname ;
11254     sym_link *rtype, *retype;    
11255
11256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11257
11258     rtype = operandType(result);
11259     retype= getSpec(rtype);
11260     
11261     pic16_aopOp(left,ic,FALSE);
11262
11263   /* if the value is already in a pointer register
11264        then don't need anything more */
11265     if (!AOP_INPREG(AOP(left))) {
11266         /* otherwise get a free pointer register */
11267         aop = newAsmop(0);
11268         preg = getFreePtr(ic,&aop,FALSE);
11269         pic16_emitcode("mov","%s,%s",
11270                 preg->name,
11271                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11272         rname = preg->name ;
11273     } else
11274         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11275     
11276     pic16_freeAsmop(left,NULL,ic,TRUE);
11277     pic16_aopOp (result,ic,FALSE);
11278
11279     /* if bitfield then unpack the bits */
11280     if (IS_BITFIELD(retype)) 
11281         genUnpackBits (result,left,rname,PPOINTER);
11282     else {
11283         /* we have can just get the values */
11284         int size = AOP_SIZE(result);
11285         int offset = 0 ;        
11286         
11287         while (size--) {
11288             
11289             pic16_emitcode("movx","a,@%s",rname);
11290             pic16_aopPut(AOP(result),"a",offset);
11291             
11292             offset++ ;
11293             
11294             if (size)
11295                 pic16_emitcode("inc","%s",rname);
11296         }
11297     }
11298
11299     /* now some housekeeping stuff */
11300     if (aop) {
11301         /* we had to allocate for this iCode */
11302         pic16_freeAsmop(NULL,aop,ic,TRUE);
11303     } else { 
11304         /* we did not allocate which means left
11305            already in a pointer register, then
11306            if size > 0 && this could be used again
11307            we have to point it back to where it 
11308            belongs */
11309         if (AOP_SIZE(result) > 1 &&
11310             !OP_SYMBOL(left)->remat &&
11311             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11312               ic->depth )) {
11313             int size = AOP_SIZE(result) - 1;
11314             while (size--)
11315                 pic16_emitcode("dec","%s",rname);
11316         }
11317     }
11318
11319     /* done */
11320     pic16_freeAsmop(result,NULL,ic,TRUE);
11321     
11322         
11323 }
11324
11325 /*-----------------------------------------------------------------*/
11326 /* genFarPointerGet - gget value from far space                    */
11327 /*-----------------------------------------------------------------*/
11328 static void genFarPointerGet (operand *left,
11329                               operand *result, iCode *ic)
11330 {
11331     int size, offset ;
11332     sym_link *retype = getSpec(operandType(result));
11333
11334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11335
11336     pic16_aopOp(left,ic,FALSE);
11337
11338     /* if the operand is already in dptr 
11339     then we do nothing else we move the value to dptr */
11340     if (AOP_TYPE(left) != AOP_STR) {
11341         /* if this is remateriazable */
11342         if (AOP_TYPE(left) == AOP_IMMD)
11343             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11344         else { /* we need to get it byte by byte */
11345             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11346             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11347             if (options.model == MODEL_FLAT24)
11348             {
11349                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11350             }
11351         }
11352     }
11353     /* so dptr know contains the address */
11354     pic16_freeAsmop(left,NULL,ic,TRUE);
11355     pic16_aopOp(result,ic,FALSE);
11356
11357     /* if bit then unpack */
11358     if (IS_BITFIELD(retype)) 
11359         genUnpackBits(result,left,"dptr",FPOINTER);
11360     else {
11361         size = AOP_SIZE(result);
11362         offset = 0 ;
11363
11364         while (size--) {
11365             pic16_emitcode("movx","a,@dptr");
11366             pic16_aopPut(AOP(result),"a",offset++);
11367             if (size)
11368                 pic16_emitcode("inc","dptr");
11369         }
11370     }
11371
11372     pic16_freeAsmop(result,NULL,ic,TRUE);
11373 }
11374
11375 #if 0
11376 /*-----------------------------------------------------------------*/
11377 /* genCodePointerGet - get value from code space                  */
11378 /*-----------------------------------------------------------------*/
11379 static void genCodePointerGet (operand *left,
11380                                 operand *result, iCode *ic)
11381 {
11382     int size, offset ;
11383     sym_link *retype = getSpec(operandType(result));
11384
11385     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11386
11387     pic16_aopOp(left,ic,FALSE);
11388
11389     /* if the operand is already in dptr 
11390     then we do nothing else we move the value to dptr */
11391     if (AOP_TYPE(left) != AOP_STR) {
11392         /* if this is remateriazable */
11393         if (AOP_TYPE(left) == AOP_IMMD)
11394             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11395         else { /* we need to get it byte by byte */
11396             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11397             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11398             if (options.model == MODEL_FLAT24)
11399             {
11400                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11401             }
11402         }
11403     }
11404     /* so dptr know contains the address */
11405     pic16_freeAsmop(left,NULL,ic,TRUE);
11406     pic16_aopOp(result,ic,FALSE);
11407
11408     /* if bit then unpack */
11409     if (IS_BITFIELD(retype)) 
11410         genUnpackBits(result,left,"dptr",CPOINTER);
11411     else {
11412         size = AOP_SIZE(result);
11413         offset = 0 ;
11414
11415         while (size--) {
11416             pic16_emitcode("clr","a");
11417             pic16_emitcode("movc","a,@a+dptr");
11418             pic16_aopPut(AOP(result),"a",offset++);
11419             if (size)
11420                 pic16_emitcode("inc","dptr");
11421         }
11422     }
11423
11424     pic16_freeAsmop(result,NULL,ic,TRUE);
11425 }
11426 #endif
11427
11428 #if 0
11429 /*-----------------------------------------------------------------*/
11430 /* genGenPointerGet - gget value from generic pointer space        */
11431 /*-----------------------------------------------------------------*/
11432 static void genGenPointerGet (operand *left,
11433                               operand *result, iCode *ic)
11434 {
11435   int size, offset, lit;
11436   sym_link *retype = getSpec(operandType(result));
11437
11438         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11439         pic16_aopOp(left,ic,FALSE);
11440         pic16_aopOp(result,ic,FALSE);
11441         size = AOP_SIZE(result);
11442
11443         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11444
11445         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11446
11447                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11448                 // load FSR0 from immediate
11449                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11450
11451 //              pic16_loadFSR0( left );
11452
11453                 offset = 0;
11454                 while(size--) {
11455                         if(size) {
11456                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11457                         } else {
11458                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11459                         }
11460                         offset++;
11461                 }
11462                 goto release;
11463
11464         }
11465         else { /* we need to get it byte by byte */
11466                 // set up FSR0 with address from left
11467                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11468                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11469
11470                 offset = 0 ;
11471
11472                 while(size--) {
11473                         if(size) {
11474                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11475                         } else {
11476                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11477                         }
11478                         offset++;
11479                 }
11480                 goto release;
11481         }
11482
11483   /* if bit then unpack */
11484         if (IS_BITFIELD(retype)) 
11485                 genUnpackBits(result,left,"BAD",GPOINTER);
11486
11487         release:
11488         pic16_freeAsmop(left,NULL,ic,TRUE);
11489         pic16_freeAsmop(result,NULL,ic,TRUE);
11490
11491 }
11492 #endif
11493
11494
11495 /*-----------------------------------------------------------------*/
11496 /* genGenPointerGet - gget value from generic pointer space        */
11497 /*-----------------------------------------------------------------*/
11498 static void genGenPointerGet (operand *left,
11499                               operand *result, iCode *ic)
11500 {
11501   int size, offset, lit;
11502   sym_link *retype = getSpec(operandType(result));
11503   char fgptrget[32];
11504
11505     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11506     pic16_aopOp(left,ic,FALSE);
11507     pic16_aopOp(result,ic,FALSE);
11508     size = AOP_SIZE(result);
11509
11510     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11511
11512     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11513
11514       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11515       // load FSR0 from immediate
11516       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11517
11518       werror(W_POSSBUG2, __FILE__, __LINE__);
11519
11520       offset = 0;
11521       while(size--) {
11522         if(size) {
11523           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11524         } else {
11525           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11526         }
11527         offset++;
11528       }
11529
11530       goto release;
11531
11532     } else { /* we need to get it byte by byte */
11533
11534       /* set up WREG:PRODL:FSR0L with address from left */
11535       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11536       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11537       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11538       
11539       switch( size ) {
11540         case 1: strcpy(fgptrget, "__gptrget1"); break;
11541         case 2: strcpy(fgptrget, "__gptrget2"); break;
11542         case 3: strcpy(fgptrget, "__gptrget3"); break;
11543         case 4: strcpy(fgptrget, "__gptrget4"); break;
11544         default:
11545           werror(W_POSSBUG2, __FILE__, __LINE__);
11546           abort();
11547       }
11548       
11549       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11550       
11551       assignResultValue(result, 1);
11552       
11553       {
11554         symbol *sym;
11555
11556           sym = newSymbol( fgptrget, 0 );
11557           strcpy(sym->rname, fgptrget);
11558           checkAddSym(&externs, sym);
11559
11560 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11561       }
11562               
11563       goto release;
11564     }
11565
11566   /* if bit then unpack */
11567     if (IS_BITFIELD(retype)) 
11568       genUnpackBits(result,left,"BAD",GPOINTER);
11569
11570 release:
11571   pic16_freeAsmop(left,NULL,ic,TRUE);
11572   pic16_freeAsmop(result,NULL,ic,TRUE);
11573 }
11574
11575 /*-----------------------------------------------------------------*/
11576 /* genConstPointerGet - get value from const generic pointer space */
11577 /*-----------------------------------------------------------------*/
11578 static void genConstPointerGet (operand *left,
11579                                 operand *result, iCode *ic)
11580 {
11581   //sym_link *retype = getSpec(operandType(result));
11582   // symbol *albl = newiTempLabel(NULL);        // patch 15
11583   // symbol *blbl = newiTempLabel(NULL);        //
11584   // PIC_OPCODE poc;                            // patch 15
11585   int size;
11586   int offset = 0;
11587
11588   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11589   pic16_aopOp(left,ic,FALSE);
11590   pic16_aopOp(result,ic,TRUE);
11591   size = AOP_SIZE(result);
11592
11593   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11594
11595   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11596
11597   // set up table pointer
11598   if( (AOP_TYPE(left) == AOP_PCODE) 
11599       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11600           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11601     {
11602       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11603       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11604       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11605       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11606       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11607       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11608   } else {
11609     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11610     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11611     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11612   }
11613
11614   while(size--) {
11615     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11616     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11617     offset++;
11618   }
11619     
11620   pic16_freeAsmop(left,NULL,ic,TRUE);
11621   pic16_freeAsmop(result,NULL,ic,TRUE);
11622 }
11623
11624
11625 /*-----------------------------------------------------------------*/
11626 /* genPointerGet - generate code for pointer get                   */
11627 /*-----------------------------------------------------------------*/
11628 static void genPointerGet (iCode *ic)
11629 {
11630   operand *left, *result ;
11631   sym_link *type, *etype;
11632   int p_type;
11633
11634     FENTRY;
11635     
11636     left = IC_LEFT(ic);
11637     result = IC_RESULT(ic) ;
11638
11639     /* depending on the type of pointer we need to
11640     move it to the correct pointer register */
11641     type = operandType(left);
11642     etype = getSpec(type);
11643
11644 #if 0
11645     if (IS_PTR_CONST(type))
11646 #else
11647     if (IS_CODEPTR(type))
11648 #endif
11649       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11650
11651     /* if left is of type of pointer then it is simple */
11652     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11653       p_type = DCL_TYPE(type);
11654     else {
11655       /* we have to go by the storage class */
11656       p_type = PTR_TYPE(SPEC_OCLS(etype));
11657
11658       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11659
11660       if (SPEC_OCLS(etype)->codesp ) {
11661         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11662         //p_type = CPOINTER ;   
11663       } else
11664       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11665         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11666         /*p_type = FPOINTER ;*/ 
11667       } else
11668       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11669         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11670         /* p_type = PPOINTER; */
11671       } else
11672       if (SPEC_OCLS(etype) == idata ) {
11673         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11674         /* p_type = IPOINTER; */
11675       } else {
11676         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11677         /* p_type = POINTER ; */
11678       }
11679     }
11680
11681     /* now that we have the pointer type we assign
11682     the pointer values */
11683     switch (p_type) {
11684       case POINTER:     
11685       case IPOINTER:
11686         genNearPointerGet (left,result,ic);
11687         break;
11688
11689       case PPOINTER:
11690         genPagedPointerGet(left,result,ic);
11691         break;
11692
11693       case FPOINTER:
11694         genFarPointerGet (left,result,ic);
11695         break;
11696
11697       case CPOINTER:
11698         genConstPointerGet (left,result,ic);
11699         //pic16_emitcodePointerGet (left,result,ic);
11700         break;
11701
11702       case GPOINTER:
11703 #if 0
11704       if (IS_PTR_CONST(type))
11705         genConstPointerGet (left,result,ic);
11706       else
11707 #endif
11708         genGenPointerGet (left,result,ic);
11709       break;
11710
11711     default:
11712       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11713               "genPointerGet: illegal pointer type");
11714     
11715     }
11716 }
11717
11718 /*-----------------------------------------------------------------*/
11719 /* genPackBits - generates code for packed bit storage             */
11720 /*-----------------------------------------------------------------*/
11721 static void genPackBits (sym_link    *etype , operand *result,
11722                          operand *right ,
11723                          char *rname, int p_type)
11724 {
11725   int shCnt = 0 ;
11726   int offset = 0  ;
11727   int rLen = 0 ;
11728   int blen, bstr ;   
11729   sym_link *retype;
11730   char *l ;
11731
11732         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11733         blen = SPEC_BLEN(etype);
11734         bstr = SPEC_BSTR(etype);
11735
11736         retype = getSpec(operandType(right));
11737
11738         if(AOP_TYPE(right) == AOP_LIT) {
11739                 if((blen == 1) && (bstr < 8)) {
11740                   unsigned long lit;
11741                         /* it is a single bit, so use the appropriate bit instructions */
11742
11743                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11744
11745                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11746 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11747                         if((p_type == POINTER) && (result)) {
11748                                 /* workaround to reduce the extra lfsr instruction */
11749                                 if(lit) {
11750                                         pic16_emitpcode(POC_BSF,
11751                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11752                                 } else {
11753                                         pic16_emitpcode(POC_BCF,
11754                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11755                                 }
11756                         } else {
11757                                 pic16_loadFSR0( result );
11758                                 if(lit) {
11759                                         pic16_emitpcode(POC_BSF,
11760                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11761                                 } else {
11762                                         pic16_emitpcode(POC_BCF,
11763                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11764                                 }
11765                         }
11766         
11767                   return;
11768                 }
11769
11770                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11771                 offset++;
11772         } else
11773         if(IS_BITFIELD(retype) 
11774           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11775           && (blen == 1)) {
11776           int rblen, rbstr;
11777
11778             rblen = SPEC_BLEN( retype );
11779             rbstr = SPEC_BSTR( retype );
11780             
11781
11782             if(IS_BITFIELD(etype)) {
11783               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11784               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11785             } else {
11786               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11787             }
11788             
11789             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11790             
11791             if(IS_BITFIELD(etype)) {
11792               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11793             } else {
11794               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11795             }
11796
11797             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11798             
11799             return;
11800         } else
11801           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11802
11803         /* if the bit lenth is less than or    */
11804         /* it exactly fits a byte then         */
11805         if((shCnt=SPEC_BSTR(etype))
11806                 || SPEC_BLEN(etype) <= 8 )  {
11807
11808                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11809
11810                 /* shift left acc */
11811                 AccLsh(shCnt);
11812
11813                 /* using PRODL as a temporary register here */
11814                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11815
11816                 switch (p_type) {
11817                         case FPOINTER:
11818                         case POINTER:
11819                                 pic16_loadFSR0( result );
11820                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11821 //                              pic16_emitcode ("mov","b,a");
11822 //                              pic16_emitcode("mov","a,@%s",rname);
11823                                 break;
11824
11825                         case GPOINTER:
11826                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11827                                 break;
11828
11829                 }
11830 #if 1
11831                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11832                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11833                                         (unsigned char)(0xff >> (8-bstr))) ));
11834                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11835                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11836 #endif
11837
11838           return;
11839         }
11840
11841
11842         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11843         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11844         exit(-1);
11845
11846
11847     /* if we r done */
11848     if ( SPEC_BLEN(etype) <= 8 )
11849         return ;
11850
11851     pic16_emitcode("inc","%s",rname);
11852     rLen = SPEC_BLEN(etype) ;     
11853
11854
11855
11856     /* now generate for lengths greater than one byte */
11857     while (1) {
11858
11859         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11860
11861         rLen -= 8 ;
11862         if (rLen <= 0 )
11863             break ;
11864
11865         switch (p_type) {
11866             case POINTER:
11867                 if (*l == '@') {
11868                     MOVA(l);
11869                     pic16_emitcode("mov","@%s,a",rname);
11870                 } else
11871                     pic16_emitcode("mov","@%s,%s",rname,l);
11872                 break;
11873
11874             case FPOINTER:
11875                 MOVA(l);
11876                 pic16_emitcode("movx","@dptr,a");
11877                 break;
11878
11879             case GPOINTER:
11880                 MOVA(l);
11881                 DEBUGpic16_emitcode(";lcall","__gptrput");
11882                 break;  
11883         }   
11884         pic16_emitcode ("inc","%s",rname);
11885     }
11886
11887     MOVA(l);
11888
11889     /* last last was not complete */
11890     if (rLen)   {
11891         /* save the byte & read byte */
11892         switch (p_type) {
11893             case POINTER:
11894                 pic16_emitcode ("mov","b,a");
11895                 pic16_emitcode("mov","a,@%s",rname);
11896                 break;
11897
11898             case FPOINTER:
11899                 pic16_emitcode ("mov","b,a");
11900                 pic16_emitcode("movx","a,@dptr");
11901                 break;
11902
11903             case GPOINTER:
11904                 pic16_emitcode ("push","b");
11905                 pic16_emitcode ("push","acc");
11906                 pic16_emitcode ("lcall","__gptrget");
11907                 pic16_emitcode ("pop","b");
11908                 break;
11909         }
11910
11911         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11912         pic16_emitcode ("orl","a,b");
11913     }
11914
11915     if (p_type == GPOINTER)
11916         pic16_emitcode("pop","b");
11917
11918     switch (p_type) {
11919
11920     case POINTER:
11921         pic16_emitcode("mov","@%s,a",rname);
11922         break;
11923         
11924     case FPOINTER:
11925         pic16_emitcode("movx","@dptr,a");
11926         break;
11927         
11928     case GPOINTER:
11929         DEBUGpic16_emitcode(";lcall","__gptrput");
11930         break;                  
11931     }
11932 }
11933 /*-----------------------------------------------------------------*/
11934 /* genDataPointerSet - remat pointer to data space                 */
11935 /*-----------------------------------------------------------------*/
11936 static void genDataPointerSet(operand *right,
11937                               operand *result,
11938                               iCode *ic)
11939 {
11940     int size, offset = 0, resoffset=0 ;
11941
11942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11943     pic16_aopOp(right,ic,FALSE);
11944
11945     size = AOP_SIZE(right);
11946
11947 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11948
11949 #if 0
11950     if ( AOP_TYPE(result) == AOP_PCODE) {
11951       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11952               AOP(result)->aopu.pcop->name,
11953                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11954               PCOR(AOP(result)->aopu.pcop)->instance:
11955               PCOI(AOP(result)->aopu.pcop)->offset);
11956     }
11957 #endif
11958
11959         if(AOP(result)->aopu.pcop->type == PO_DIR)
11960                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11961
11962         while (size--) {
11963                 if (AOP_TYPE(right) == AOP_LIT) {
11964                   unsigned int lit;
11965
11966                     if(!IS_FLOAT(operandType( right )))
11967                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11968                     else {
11969                       union {
11970                         unsigned long lit_int;
11971                         float lit_float;
11972                       } info;
11973         
11974                         /* take care if literal is a float */
11975                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11976                         lit = info.lit_int;
11977                     }
11978
11979                     lit = lit >> (8*offset);
11980                     if(lit&0xff) {
11981                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11982                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11983                     } else {
11984                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11985                     }
11986                 } else {
11987                   pic16_mov2w(AOP(right), offset);
11988                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11989                 }
11990                 offset++;
11991                 resoffset++;
11992         }
11993
11994     pic16_freeAsmop(right,NULL,ic,TRUE);
11995 }
11996
11997
11998
11999 /*-----------------------------------------------------------------*/
12000 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12001 /*-----------------------------------------------------------------*/
12002 static void genNearPointerSet (operand *right,
12003                                operand *result, 
12004                                iCode *ic)
12005 {
12006   asmop *aop = NULL;
12007   char *l;
12008   sym_link *retype;
12009   sym_link *ptype = operandType(result);
12010   sym_link *resetype;
12011     
12012         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12013         retype= getSpec(operandType(right));
12014         resetype = getSpec(operandType(result));
12015   
12016         pic16_aopOp(result,ic,FALSE);
12017     
12018         /* if the result is rematerializable &
12019          * in data space & not a bit variable */
12020         
12021         /* and result is not a bit variable */
12022         if (AOP_TYPE(result) == AOP_PCODE
12023 //              && AOP_TYPE(result) == AOP_IMMD
12024                 && DCL_TYPE(ptype) == POINTER
12025                 && !IS_BITFIELD(retype)
12026                 && !IS_BITFIELD(resetype)) {
12027
12028                 genDataPointerSet (right,result,ic);
12029                 pic16_freeAsmop(result,NULL,ic,TRUE);
12030           return;
12031         }
12032
12033         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12034         pic16_aopOp(right,ic,FALSE);
12035         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12036
12037         /* if the value is already in a pointer register
12038          * then don't need anything more */
12039         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12040                 /* otherwise get a free pointer register */
12041                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12042
12043 //              if( (AOP_TYPE(result) == AOP_PCODE) 
12044 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12045 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12046                 if(is_LitAOp( AOP(result) ))
12047                 {
12048                   if(!IS_BITFIELD(resetype))
12049                         pic16_loadFSR0( result );  // patch 10
12050                 } else {
12051                   if(!IS_BITFIELD(resetype)) {
12052                         // set up FSR0 with address of result
12053                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12054                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12055                   }
12056                 }
12057
12058         }
12059 //      else
12060 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12061
12062         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12063
12064 //      pic16_loadFSR0( result );
12065
12066         /* if bitfield then unpack the bits */
12067         if (IS_BITFIELD(resetype)) {
12068                 genPackBits (resetype, result, right, NULL, POINTER);
12069         } else {
12070                 /* we have can just get the values */
12071           int size = AOP_SIZE(right);
12072           int offset = 0 ;    
12073
12074                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12075                 while (size--) {
12076                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12077                         if (*l == '@' ) {
12078                                 //MOVA(l);
12079                                 //pic16_emitcode("mov","@%s,a",rname);
12080                                 pic16_emitcode("movf","indf0,w ;1");
12081                         } else {
12082
12083                                 if (AOP_TYPE(right) == AOP_LIT) {
12084                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12085                                         if (size) {
12086                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12087                                         } else {
12088                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12089                                         }
12090                                 } else { // no literal
12091                                         if(size) {
12092                                                 pic16_emitpcode(POC_MOVFF,
12093                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12094                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12095                                         } else {
12096                                                 pic16_emitpcode(POC_MOVFF,
12097                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12098                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12099                                         }
12100                                 }
12101                         }
12102                         offset++;
12103                 }
12104         }
12105
12106         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12107         /* now some housekeeping stuff */
12108         if (aop) {
12109                 /* we had to allocate for this iCode */
12110                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12111         } else { 
12112                 /* we did not allocate which means left
12113                  * already in a pointer register, then
12114                  * if size > 0 && this could be used again
12115                  * we have to point it back to where it 
12116                  * belongs */
12117                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12118                 if (AOP_SIZE(right) > 1
12119                         && !OP_SYMBOL(result)->remat
12120                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12121                                 || ic->depth )) {
12122
12123                   int size = AOP_SIZE(right) - 1;
12124
12125                         while (size--)
12126                                 pic16_emitcode("decf","fsr0,f");
12127                         //pic16_emitcode("dec","%s",rname);
12128                 }
12129         }
12130
12131         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12132         /* done */
12133 //release:
12134         pic16_freeAsmop(right,NULL,ic,TRUE);
12135         pic16_freeAsmop(result,NULL,ic,TRUE);
12136 }
12137
12138 /*-----------------------------------------------------------------*/
12139 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12140 /*-----------------------------------------------------------------*/
12141 static void genPagedPointerSet (operand *right,
12142                                operand *result, 
12143                                iCode *ic)
12144 {
12145     asmop *aop = NULL;
12146     regs *preg = NULL ;
12147     char *rname , *l;
12148     sym_link *retype;
12149        
12150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12151
12152     retype= getSpec(operandType(right));
12153     
12154     pic16_aopOp(result,ic,FALSE);
12155     
12156     /* if the value is already in a pointer register
12157        then don't need anything more */
12158     if (!AOP_INPREG(AOP(result))) {
12159         /* otherwise get a free pointer register */
12160         aop = newAsmop(0);
12161         preg = getFreePtr(ic,&aop,FALSE);
12162         pic16_emitcode("mov","%s,%s",
12163                 preg->name,
12164                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12165         rname = preg->name ;
12166     } else
12167         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12168     
12169     pic16_freeAsmop(result,NULL,ic,TRUE);
12170     pic16_aopOp (right,ic,FALSE);
12171
12172     /* if bitfield then unpack the bits */
12173     if (IS_BITFIELD(retype)) 
12174         genPackBits (retype,result,right,rname,PPOINTER);
12175     else {
12176         /* we have can just get the values */
12177         int size = AOP_SIZE(right);
12178         int offset = 0 ;        
12179         
12180         while (size--) {
12181             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12182             
12183             MOVA(l);
12184             pic16_emitcode("movx","@%s,a",rname);
12185
12186             if (size)
12187                 pic16_emitcode("inc","%s",rname);
12188
12189             offset++;
12190         }
12191     }
12192     
12193     /* now some housekeeping stuff */
12194     if (aop) {
12195         /* we had to allocate for this iCode */
12196         pic16_freeAsmop(NULL,aop,ic,TRUE);
12197     } else { 
12198         /* we did not allocate which means left
12199            already in a pointer register, then
12200            if size > 0 && this could be used again
12201            we have to point it back to where it 
12202            belongs */
12203         if (AOP_SIZE(right) > 1 &&
12204             !OP_SYMBOL(result)->remat &&
12205             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12206               ic->depth )) {
12207             int size = AOP_SIZE(right) - 1;
12208             while (size--)
12209                 pic16_emitcode("dec","%s",rname);
12210         }
12211     }
12212
12213     /* done */
12214     pic16_freeAsmop(right,NULL,ic,TRUE);
12215     
12216         
12217 }
12218
12219 /*-----------------------------------------------------------------*/
12220 /* genFarPointerSet - set value from far space                     */
12221 /*-----------------------------------------------------------------*/
12222 static void genFarPointerSet (operand *right,
12223                               operand *result, iCode *ic)
12224 {
12225     int size, offset ;
12226     sym_link *retype = getSpec(operandType(right));
12227
12228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12229     pic16_aopOp(result,ic,FALSE);
12230
12231     /* if the operand is already in dptr 
12232     then we do nothing else we move the value to dptr */
12233     if (AOP_TYPE(result) != AOP_STR) {
12234         /* if this is remateriazable */
12235         if (AOP_TYPE(result) == AOP_IMMD)
12236             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12237         else { /* we need to get it byte by byte */
12238             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12239             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12240             if (options.model == MODEL_FLAT24)
12241             {
12242                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12243             }
12244         }
12245     }
12246     /* so dptr know contains the address */
12247     pic16_freeAsmop(result,NULL,ic,TRUE);
12248     pic16_aopOp(right,ic,FALSE);
12249
12250     /* if bit then unpack */
12251     if (IS_BITFIELD(retype)) 
12252         genPackBits(retype,result,right,"dptr",FPOINTER);
12253     else {
12254         size = AOP_SIZE(right);
12255         offset = 0 ;
12256
12257         while (size--) {
12258             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12259             MOVA(l);
12260             pic16_emitcode("movx","@dptr,a");
12261             if (size)
12262                 pic16_emitcode("inc","dptr");
12263         }
12264     }
12265
12266     pic16_freeAsmop(right,NULL,ic,TRUE);
12267 }
12268
12269 /*-----------------------------------------------------------------*/
12270 /* genGenPointerSet - set value from generic pointer space         */
12271 /*-----------------------------------------------------------------*/
12272 #if 0
12273 static void genGenPointerSet (operand *right,
12274                               operand *result, iCode *ic)
12275 {
12276         int i, size, offset, lit;
12277         sym_link *retype = getSpec(operandType(right));
12278
12279         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12280
12281         pic16_aopOp(result,ic,FALSE);
12282         pic16_aopOp(right,ic,FALSE);
12283         size = AOP_SIZE(right);
12284         offset = 0;
12285
12286         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12287
12288         /* if the operand is already in dptr 
12289                 then we do nothing else we move the value to dptr */
12290         if (AOP_TYPE(result) != AOP_STR) {
12291                 /* if this is remateriazable */
12292                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12293                 // WARNING: anythig until "else" is untested!
12294                 if (AOP_TYPE(result) == AOP_IMMD) {
12295                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12296                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12297                         // load FSR0 from immediate
12298                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12299                         offset = 0;
12300                         while(size--) {
12301                                 if(size) {
12302                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12303                                 } else {
12304                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12305                                 }
12306                                 offset++;
12307                         }
12308                         goto release;
12309                 }
12310                 else { /* we need to get it byte by byte */
12311                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12312                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12313
12314                         // set up FSR0 with address of result
12315                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12316                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12317
12318                         /* hack hack! see if this the FSR. If so don't load W */
12319                         if(AOP_TYPE(right) != AOP_ACC) {
12320
12321                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12322
12323                                 if(AOP_TYPE(right) == AOP_LIT)
12324                                 {
12325                                         // copy literal
12326                                         // note: pic16_popGet handles sign extension
12327                                         for(i=0;i<size;i++) {
12328                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12329                                                 if(i < size-1)
12330                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12331                                                 else
12332                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12333                                         }
12334                                 } else {
12335                                         // copy regs
12336
12337                                         for(i=0;i<size;i++) {
12338                                                 if(i < size-1)
12339                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12340                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12341                                                 else
12342                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12343                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12344                                         }
12345                                 }
12346                                 goto release;
12347                         } 
12348                         // right = ACC
12349                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12350                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12351                         goto release;
12352         } // if (AOP_TYPE(result) != AOP_IMMD)
12353
12354         } // if (AOP_TYPE(result) != AOP_STR)
12355         /* so dptr know contains the address */
12356
12357
12358         /* if bit then unpack */
12359         if (IS_BITFIELD(retype)) 
12360                 genPackBits(retype,result,right,"dptr",GPOINTER);
12361         else {
12362                 size = AOP_SIZE(right);
12363                 offset = 0 ;
12364
12365                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12366
12367                 // set up FSR0 with address of result
12368                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12369                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12370         
12371                 while (size--) {
12372                         if (AOP_TYPE(right) == AOP_LIT) {
12373                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12374                                 if (size) {
12375                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12376                                 } else {
12377                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12378                                 }
12379                         } else { // no literal
12380                                 if(size) {
12381                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12382                                 } else {
12383                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12384                                 }
12385                         }
12386                         offset++;
12387                 }
12388         }
12389
12390         release:
12391         pic16_freeAsmop(right,NULL,ic,TRUE);
12392         pic16_freeAsmop(result,NULL,ic,TRUE);
12393 }
12394 #endif
12395
12396 static void genGenPointerSet (operand *right,
12397                               operand *result, iCode *ic)
12398 {
12399   int size;
12400   sym_link *retype = getSpec(operandType(right));
12401   char fgptrput[32];
12402
12403     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12404
12405     pic16_aopOp(result,ic,FALSE);
12406     pic16_aopOp(right,ic,FALSE);
12407     size = AOP_SIZE(right);
12408
12409     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12410
12411
12412     /* if bit then unpack */
12413     if (IS_BITFIELD(retype)) {
12414 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12415       genPackBits(retype,result,right,"dptr",GPOINTER);
12416       goto release;
12417     }
12418
12419     size = AOP_SIZE(right);
12420
12421     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12422
12423
12424
12425     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12426
12427     /* value of right+0 is placed on stack, which will be retrieved
12428      * by the support function this restoring the stack. The important
12429      * thing is that there is no need to manually restore stack pointer
12430      * here */
12431     pushaop(AOP(right), 0);
12432 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12433     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12434     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12435     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12436     
12437     /* load address to write to in WREG:FSR0H:FSR0L */
12438     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12439                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12440     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12441                                 pic16_popCopyReg(&pic16_pc_prodl)));
12442     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12443     
12444
12445     /* put code here */
12446     switch (size) {
12447       case 1: strcpy(fgptrput, "__gptrput1"); break;
12448       case 2: strcpy(fgptrput, "__gptrput2"); break;
12449       case 3: strcpy(fgptrput, "__gptrput3"); break;
12450       case 4: strcpy(fgptrput, "__gptrput4"); break;
12451       default:
12452         werror(W_POSSBUG2, __FILE__, __LINE__);
12453         abort();
12454     }
12455     
12456     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12457     
12458     {
12459       symbol *sym;
12460                   
12461         sym = newSymbol( fgptrput, 0 );
12462         strcpy(sym->rname, fgptrput);
12463         checkAddSym(&externs, sym);
12464     }
12465
12466 release:
12467     pic16_freeAsmop(right,NULL,ic,TRUE);
12468     pic16_freeAsmop(result,NULL,ic,TRUE);
12469 }
12470
12471 /*-----------------------------------------------------------------*/
12472 /* genPointerSet - stores the value into a pointer location        */
12473 /*-----------------------------------------------------------------*/
12474 static void genPointerSet (iCode *ic)
12475 {    
12476   operand *right, *result ;
12477   sym_link *type, *etype;
12478   int p_type;
12479
12480     FENTRY;
12481
12482     right = IC_RIGHT(ic);
12483     result = IC_RESULT(ic) ;
12484
12485     /* depending on the type of pointer we need to
12486     move it to the correct pointer register */
12487     type = operandType(result);
12488     etype = getSpec(type);
12489     /* if left is of type of pointer then it is simple */
12490     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12491         p_type = DCL_TYPE(type);
12492     }
12493     else {
12494         /* we have to go by the storage class */
12495         p_type = PTR_TYPE(SPEC_OCLS(etype));
12496
12497 /*      if (SPEC_OCLS(etype)->codesp ) { */
12498 /*          p_type = CPOINTER ;  */
12499 /*      } */
12500 /*      else */
12501 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12502 /*              p_type = FPOINTER ; */
12503 /*          else */
12504 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12505 /*                  p_type = PPOINTER ; */
12506 /*              else */
12507 /*                  if (SPEC_OCLS(etype) == idata ) */
12508 /*                      p_type = IPOINTER ; */
12509 /*                  else */
12510 /*                      p_type = POINTER ; */
12511     }
12512
12513     /* now that we have the pointer type we assign
12514     the pointer values */
12515     switch (p_type) {
12516       case POINTER:
12517       case IPOINTER:
12518         genNearPointerSet (right,result,ic);
12519         break;
12520
12521       case PPOINTER:
12522         genPagedPointerSet (right,result,ic);
12523         break;
12524
12525       case FPOINTER:
12526         genFarPointerSet (right,result,ic);
12527         break;
12528         
12529       case GPOINTER:
12530         genGenPointerSet (right,result,ic);
12531         break;
12532
12533       default:
12534         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12535           "genPointerSet: illegal pointer type");
12536     }
12537 }
12538
12539 /*-----------------------------------------------------------------*/
12540 /* genIfx - generate code for Ifx statement                        */
12541 /*-----------------------------------------------------------------*/
12542 static void genIfx (iCode *ic, iCode *popIc)
12543 {
12544   operand *cond = IC_COND(ic);
12545   int isbit =0;
12546
12547     FENTRY;
12548
12549     pic16_aopOp(cond,ic,FALSE);
12550
12551     /* get the value into acc */
12552     if (AOP_TYPE(cond) != AOP_CRY)
12553       pic16_toBoolean(cond);
12554     else
12555       isbit = 1;
12556     /* the result is now in the accumulator */
12557     pic16_freeAsmop(cond,NULL,ic,TRUE);
12558
12559     /* if there was something to be popped then do it */
12560     if (popIc)
12561       genIpop(popIc);
12562
12563     /* if the condition is  a bit variable */
12564     if (isbit && IS_ITEMP(cond) && 
12565         SPIL_LOC(cond)) {
12566       genIfxJump(ic,"c");
12567       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12568     } else {
12569       if (isbit && !IS_ITEMP(cond))
12570         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12571         else
12572         genIfxJump(ic,"a");
12573     }
12574     ic->generated = 1;
12575 }
12576
12577 /*-----------------------------------------------------------------*/
12578 /* genAddrOf - generates code for address of                       */
12579 /*-----------------------------------------------------------------*/
12580 static void genAddrOf (iCode *ic)
12581 {
12582   operand *result, *left;
12583   int size;
12584   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12585   pCodeOp *pcop0, *pcop1, *pcop2;
12586
12587     FENTRY;
12588
12589     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12590
12591     sym = OP_SYMBOL( IC_LEFT(ic) );
12592     
12593     if(sym->onStack) {
12594       /* get address of symbol on stack */
12595       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12596 #if 0
12597       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12598                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12599 #endif
12600
12601       // operands on stack are accessible via "FSR2 + index" with index
12602       // starting at 2 for arguments and growing from 0 downwards for
12603       // local variables (index == 0 is not assigned so we add one here)
12604       {
12605         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12606         if (soffs <= 0) {
12607           assert (soffs < 0);
12608           soffs++;
12609         } // if
12610         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12611         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12612         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12613         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12614         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12615         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12616         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12617       }
12618
12619       goto release;
12620     }
12621         
12622 //      if(pic16_debug_verbose) {
12623 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12624 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12625 //      }
12626         
12627     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12628     size = AOP_SIZE(IC_RESULT(ic));
12629
12630     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12631     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12632     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12633         
12634     if (size == 3) {
12635       pic16_emitpcode(POC_MOVLW, pcop0);
12636       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12637       pic16_emitpcode(POC_MOVLW, pcop1);
12638       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12639       pic16_emitpcode(POC_MOVLW, pcop2);
12640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12641     } else
12642     if (size == 2) {
12643       pic16_emitpcode(POC_MOVLW, pcop0);
12644       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12645       pic16_emitpcode(POC_MOVLW, pcop1);
12646     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12647     } else {
12648       pic16_emitpcode(POC_MOVLW, pcop0);
12649       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12650     }
12651
12652     pic16_freeAsmop(left, NULL, ic, FALSE);
12653 release:
12654     pic16_freeAsmop(result,NULL,ic,TRUE);
12655 }
12656
12657
12658 #if 0
12659 /*-----------------------------------------------------------------*/
12660 /* genFarFarAssign - assignment when both are in far space         */
12661 /*-----------------------------------------------------------------*/
12662 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12663 {
12664     int size = AOP_SIZE(right);
12665     int offset = 0;
12666     char *l ;
12667     /* first push the right side on to the stack */
12668     while (size--) {
12669         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12670         MOVA(l);
12671         pic16_emitcode ("push","acc");
12672     }
12673     
12674     pic16_freeAsmop(right,NULL,ic,FALSE);
12675     /* now assign DPTR to result */
12676     pic16_aopOp(result,ic,FALSE);
12677     size = AOP_SIZE(result);
12678     while (size--) {
12679         pic16_emitcode ("pop","acc");
12680         pic16_aopPut(AOP(result),"a",--offset);
12681     }
12682     pic16_freeAsmop(result,NULL,ic,FALSE);
12683         
12684 }
12685 #endif
12686
12687 /*-----------------------------------------------------------------*/
12688 /* genAssign - generate code for assignment                        */
12689 /*-----------------------------------------------------------------*/
12690 static void genAssign (iCode *ic)
12691 {
12692   operand *result, *right;
12693   int size, offset,know_W;
12694   unsigned long lit = 0L;
12695
12696   result = IC_RESULT(ic);
12697   right  = IC_RIGHT(ic) ;
12698
12699   FENTRY;
12700   
12701   /* if they are the same */
12702   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12703     return ;
12704
12705   /* reversed order operands are aopOp'ed so that result operand
12706    * is effective in case right is a stack symbol. This maneauver
12707    * allows to use the _G.resDirect flag later */
12708   pic16_aopOp(result,ic,TRUE);
12709   pic16_aopOp(right,ic,FALSE);
12710
12711   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12712
12713   /* if they are the same registers */
12714   if (pic16_sameRegs(AOP(right),AOP(result)))
12715     goto release;
12716
12717   /* if the result is a bit */
12718   if (AOP_TYPE(result) == AOP_CRY) {
12719     /* if the right size is a literal then
12720        we know what the value is */
12721     if (AOP_TYPE(right) == AOP_LIT) {
12722           
12723       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12724                   pic16_popGet(AOP(result),0));
12725
12726       if (((int) operandLitValue(right))) 
12727         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12728                        AOP(result)->aopu.aop_dir,
12729                        AOP(result)->aopu.aop_dir);
12730       else
12731         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12732                        AOP(result)->aopu.aop_dir,
12733                        AOP(result)->aopu.aop_dir);
12734       goto release;
12735     }
12736
12737     /* the right is also a bit variable */
12738     if (AOP_TYPE(right) == AOP_CRY) {
12739       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12740       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12741       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12742
12743       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12744                      AOP(result)->aopu.aop_dir,
12745                      AOP(result)->aopu.aop_dir);
12746       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12747                      AOP(right)->aopu.aop_dir,
12748                      AOP(right)->aopu.aop_dir);
12749       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12750                      AOP(result)->aopu.aop_dir,
12751                      AOP(result)->aopu.aop_dir);
12752       goto release ;
12753     }
12754
12755     /* we need to or */
12756     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12757     pic16_toBoolean(right);
12758     emitSKPZ;
12759     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12760     //pic16_aopPut(AOP(result),"a",0);
12761     goto release ;
12762   }
12763
12764   /* bit variables done */
12765   /* general case */
12766   size = AOP_SIZE(result);
12767   offset = 0 ;
12768
12769   if(AOP_TYPE(right) == AOP_LIT) {
12770         if(!IS_FLOAT(operandType( right )))
12771                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12772         else {
12773            union {
12774               unsigned long lit_int;
12775               float lit_float;
12776             } info;
12777         
12778                 /* take care if literal is a float */
12779                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12780                 lit = info.lit_int;
12781         }
12782   }
12783
12784 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12785 //                      sizeof(unsigned long int), sizeof(float));
12786
12787
12788   if (AOP_TYPE(right) == AOP_REG) {
12789     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12790     while (size--) {
12791       
12792       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12793     } // while
12794     goto release;
12795   }
12796
12797   if(AOP_TYPE(right) != AOP_LIT
12798         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12799         && !IS_FUNC(OP_SYM_TYPE(right))
12800         ) {
12801         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12802         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12803
12804         // set up table pointer
12805         if(is_LitOp(right)) {
12806 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12807                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12808                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12809                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12810                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12811                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12812                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12813         } else {
12814 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12815                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12816                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12817                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12818                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12819                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12820                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12821         }
12822
12823         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12824         while(size--) {
12825                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12826                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12827                         pic16_popGet(AOP(result),offset)));
12828                 offset++;
12829         }
12830
12831         size = getSize(OP_SYM_ETYPE(right));
12832         if(AOP_SIZE(result) > size) {
12833                 size = AOP_SIZE(result) - size;
12834                 while(size--) {
12835                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12836                         offset++;
12837                 }
12838         }
12839         goto release;
12840   }
12841
12842
12843
12844 #if 0
12845 /* VR - What is this?! */
12846   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12847     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12848     if(aopIdx(AOP(result),0) == 4) {
12849
12850       /* this is a workaround to save value of right into wreg too,
12851        * value of wreg is going to be used later */
12852       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12853       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12855       goto release;
12856     } else
12857 //      assert(0);
12858       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12859   }
12860 #endif
12861
12862   know_W=-1;
12863   while (size--) {
12864   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12865     if(AOP_TYPE(right) == AOP_LIT) {
12866       if(lit&0xff) {
12867         if(know_W != (lit&0xff))
12868           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12869         know_W = lit&0xff;
12870         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12871       } else
12872         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12873
12874       lit >>= 8;
12875
12876     } else if (AOP_TYPE(right) == AOP_CRY) {
12877       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12878       if(offset == 0) {
12879         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12880         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12881         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12882       }
12883     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12884         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12885         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12886     } else {
12887       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12888
12889       if(!_G.resDirect)         /* use this aopForSym feature */
12890         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12891     }
12892             
12893     offset++;
12894   }
12895   
12896  release:
12897   pic16_freeAsmop (right,NULL,ic,FALSE);
12898   pic16_freeAsmop (result,NULL,ic,TRUE);
12899 }   
12900
12901 /*-----------------------------------------------------------------*/
12902 /* genJumpTab - generates code for jump table                       */
12903 /*-----------------------------------------------------------------*/
12904 static void genJumpTab (iCode *ic)
12905 {
12906   symbol *jtab;
12907   char *l;
12908   pCodeOp *jt_offs;
12909   pCodeOp *jt_offs_hi;
12910   pCodeOp *jt_label;
12911
12912     FENTRY;
12913
12914     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12915     /* get the condition into accumulator */
12916     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12917     MOVA(l);
12918     /* multiply by three */
12919     pic16_emitcode("add","a,acc");
12920     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12921
12922     jtab = newiTempLabel(NULL);
12923     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12924     pic16_emitcode("jmp","@a+dptr");
12925     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12926
12927 #if 0
12928     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12929     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12930     emitSKPNC;
12931     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12932     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12933     pic16_emitpLabel(jtab->key);
12934
12935 #else
12936
12937     jt_offs = pic16_popGetTempReg(0);
12938     jt_offs_hi = pic16_popGetTempReg(1);
12939     jt_label = pic16_popGetLabel (jtab->key);
12940     //fprintf (stderr, "Creating jump table...\n");
12941
12942     // calculate offset into jump table (idx * sizeof (GOTO))
12943     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12944     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12945     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12946     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12947     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12948     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12949     pic16_emitpcode(POC_MOVWF , jt_offs);
12950
12951     // prepare PCLATx (set to first entry in jump table)
12952     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12953     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12954     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12955     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12956     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12957
12958     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12959     pic16_emitpcode(POC_ADDWF , jt_offs);
12960     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12961     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12962     emitSKPNC;
12963     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12964
12965     // release temporaries and prepare jump into table (new PCL --> WREG)
12966     pic16_emitpcode(POC_MOVFW , jt_offs);
12967     pic16_popReleaseTempReg (jt_offs_hi, 1);
12968     pic16_popReleaseTempReg (jt_offs, 0);
12969
12970     // jump into the table
12971     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12972
12973     pic16_emitpLabelFORCE(jtab->key);
12974
12975 #endif
12976     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12977
12978     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12979     /* now generate the jump labels */
12980     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12981          jtab = setNextItem(IC_JTLABELS(ic))) {
12982 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12983         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12984         
12985     }
12986     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12987
12988 }
12989
12990 /*-----------------------------------------------------------------*/
12991 /* genMixedOperation - gen code for operators between mixed types  */
12992 /*-----------------------------------------------------------------*/
12993 /*
12994   TSD - Written for the PIC port - but this unfortunately is buggy.
12995   This routine is good in that it is able to efficiently promote 
12996   types to different (larger) sizes. Unfortunately, the temporary
12997   variables that are optimized out by this routine are sometimes
12998   used in other places. So until I know how to really parse the 
12999   iCode tree, I'm going to not be using this routine :(.
13000 */
13001 static int genMixedOperation (iCode *ic)
13002 {
13003 #if 0
13004   operand *result = IC_RESULT(ic);
13005   sym_link *ctype = operandType(IC_LEFT(ic));
13006   operand *right = IC_RIGHT(ic);
13007   int ret = 0;
13008   int big,small;
13009   int offset;
13010
13011   iCode *nextic;
13012   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13013
13014   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13015
13016   nextic = ic->next;
13017   if(!nextic)
13018     return 0;
13019
13020   nextright = IC_RIGHT(nextic);
13021   nextleft  = IC_LEFT(nextic);
13022   nextresult = IC_RESULT(nextic);
13023
13024   pic16_aopOp(right,ic,FALSE);
13025   pic16_aopOp(result,ic,FALSE);
13026   pic16_aopOp(nextright,  nextic, FALSE);
13027   pic16_aopOp(nextleft,   nextic, FALSE);
13028   pic16_aopOp(nextresult, nextic, FALSE);
13029
13030   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13031
13032     operand *t = right;
13033     right = nextright;
13034     nextright = t; 
13035
13036     pic16_emitcode(";remove right +","");
13037
13038   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13039 /*
13040     operand *t = right;
13041     right = nextleft;
13042     nextleft = t; 
13043 */
13044     pic16_emitcode(";remove left +","");
13045   } else
13046     return 0;
13047
13048   big = AOP_SIZE(nextleft);
13049   small = AOP_SIZE(nextright);
13050
13051   switch(nextic->op) {
13052
13053   case '+':
13054     pic16_emitcode(";optimize a +","");
13055     /* if unsigned or not an integral type */
13056     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13057       pic16_emitcode(";add a bit to something","");
13058     } else {
13059
13060       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13061
13062       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13063         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13064         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13065       } else
13066         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13067
13068       offset = 0;
13069       while(--big) {
13070
13071         offset++;
13072
13073         if(--small) {
13074           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13075             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13076             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13077           }
13078
13079           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13080           emitSKPNC;
13081           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13082                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13083                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13084           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13085           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13086
13087         } else {
13088           pic16_emitcode("rlf","known_zero,w");
13089
13090           /*
13091             if right is signed
13092               btfsc  right,7
13093                addlw ff
13094           */
13095           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13096             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13097             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13098           } else {
13099             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13100           }
13101         }
13102       }
13103       ret = 1;
13104     }
13105   }
13106   ret = 1;
13107
13108 release:
13109   pic16_freeAsmop(right,NULL,ic,TRUE);
13110   pic16_freeAsmop(result,NULL,ic,TRUE);
13111   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13112   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13113   if(ret)
13114     nextic->generated = 1;
13115
13116   return ret;
13117 #else
13118   return 0;
13119 #endif
13120 }
13121 /*-----------------------------------------------------------------*/
13122 /* genCast - gen code for casting                                  */
13123 /*-----------------------------------------------------------------*/
13124 static void genCast (iCode *ic)
13125 {
13126   operand *result = IC_RESULT(ic);
13127   sym_link *ctype = operandType(IC_LEFT(ic));
13128   sym_link *rtype = operandType(IC_RIGHT(ic));
13129   sym_link *restype = operandType(IC_RESULT(ic));
13130   operand *right = IC_RIGHT(ic);
13131   int size, offset ;
13132
13133
13134     FENTRY;
13135
13136         /* if they are equivalent then do nothing */
13137 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13138 //              return ;
13139
13140         pic16_aopOp(right,ic,FALSE) ;
13141         pic16_aopOp(result,ic,FALSE);
13142
13143         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13144
13145
13146         /* if the result is a bit */
13147         if (AOP_TYPE(result) == AOP_CRY) {
13148         
13149                 /* if the right size is a literal then
13150                  * we know what the value is */
13151                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13152
13153                 if (AOP_TYPE(right) == AOP_LIT) {
13154                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13155                                 pic16_popGet(AOP(result),0));
13156
13157                         if (((int) operandLitValue(right))) 
13158                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13159                                         AOP(result)->aopu.aop_dir,
13160                                         AOP(result)->aopu.aop_dir);
13161                         else
13162                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13163                                         AOP(result)->aopu.aop_dir,
13164                                         AOP(result)->aopu.aop_dir);
13165                         goto release;
13166                 }
13167
13168                 /* the right is also a bit variable */
13169                 if (AOP_TYPE(right) == AOP_CRY) {
13170                         emitCLRC;
13171                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13172
13173                         pic16_emitcode("clrc","");
13174                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13175                                 AOP(right)->aopu.aop_dir,
13176                                 AOP(right)->aopu.aop_dir);
13177                         pic16_aopPut(AOP(result),"c",0);
13178                         goto release ;
13179                 }
13180
13181                 /* we need to or */
13182                 if (AOP_TYPE(right) == AOP_REG) {
13183                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13184                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13185                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13186                 }
13187                 pic16_toBoolean(right);
13188                 pic16_aopPut(AOP(result),"a",0);
13189                 goto release ;
13190         }
13191
13192         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13193           int offset = 1;
13194
13195                 size = AOP_SIZE(result);
13196
13197                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13198
13199                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13200                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13201                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13202
13203                 while (size--)
13204                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13205
13206                 goto release;
13207         }
13208
13209         if(IS_BITFIELD(getSpec(restype))
13210           && IS_BITFIELD(getSpec(rtype))) {
13211           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13212         }
13213
13214         /* if they are the same size : or less */
13215         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13216
13217                 /* if they are in the same place */
13218                 if (pic16_sameRegs(AOP(right),AOP(result)))
13219                         goto release;
13220
13221                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13222 #if 0
13223                 if (IS_PTR_CONST(rtype))
13224 #else
13225                 if (IS_CODEPTR(rtype))
13226 #endif
13227                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13228
13229 #if 0
13230                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13231 #else
13232                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13233 #endif
13234                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13235
13236 #if 0
13237                 if(AOP_TYPE(right) == AOP_IMMD) {
13238                   pCodeOp *pcop0, *pcop1, *pcop2;
13239                   symbol *sym = OP_SYMBOL( right );
13240
13241                         size = AOP_SIZE(result);
13242                         /* low */
13243                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13244                         /* high */
13245                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13246                         /* upper */
13247                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13248         
13249                         if (size == 3) {
13250                                 pic16_emitpcode(POC_MOVLW, pcop0);
13251                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13252                                 pic16_emitpcode(POC_MOVLW, pcop1);
13253                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13254                                 pic16_emitpcode(POC_MOVLW, pcop2);
13255                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13256                         } else
13257                         if (size == 2) {
13258                                 pic16_emitpcode(POC_MOVLW, pcop0);
13259                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13260                                 pic16_emitpcode(POC_MOVLW, pcop1);
13261                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13262                         } else {
13263                                 pic16_emitpcode(POC_MOVLW, pcop0);
13264                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13265                         }
13266                 } else
13267 #endif
13268                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13269                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13270                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13271                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13272                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13273                         if(AOP_SIZE(result) <2)
13274                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13275                 } else {
13276                         /* if they in different places then copy */
13277                         size = AOP_SIZE(result);
13278                         offset = 0 ;
13279                         while (size--) {
13280                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13281                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13282                                 offset++;
13283                         }
13284                 }
13285                 goto release;
13286         }
13287
13288         /* if the result is of type pointer */
13289         if (IS_PTR(ctype)) {
13290           int p_type;
13291           sym_link *type = operandType(right);
13292           sym_link *etype = getSpec(type);
13293
13294                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13295
13296                 /* pointer to generic pointer */
13297                 if (IS_GENPTR(ctype)) {
13298                   char *l = zero;
13299             
13300                         if (IS_PTR(type)) 
13301                                 p_type = DCL_TYPE(type);
13302                         else {
13303                 /* we have to go by the storage class */
13304                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13305
13306 /*              if (SPEC_OCLS(etype)->codesp )  */
13307 /*                  p_type = CPOINTER ;  */
13308 /*              else */
13309 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13310 /*                      p_type = FPOINTER ; */
13311 /*                  else */
13312 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13313 /*                          p_type = PPOINTER; */
13314 /*                      else */
13315 /*                          if (SPEC_OCLS(etype) == idata ) */
13316 /*                              p_type = IPOINTER ; */
13317 /*                          else */
13318 /*                              p_type = POINTER ; */
13319             }
13320                 
13321             /* the first two bytes are known */
13322       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13323             size = GPTRSIZE - 1; 
13324             offset = 0 ;
13325             while (size--) {
13326               if(offset < AOP_SIZE(right)) {
13327                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13328                 mov2f(AOP(result), AOP(right), offset);
13329 /*
13330                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13331                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13332                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13333                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13334                 } else { 
13335                   
13336                   pic16_aopPut(AOP(result),
13337                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13338                          offset);
13339                 }
13340 */
13341               } else 
13342                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13343               offset++;
13344             }
13345             /* the last byte depending on type */
13346             switch (p_type) {
13347             case IPOINTER:
13348             case POINTER:
13349                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13350                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13351 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13352                 break;
13353
13354             case CPOINTER:
13355                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13356                 break;
13357
13358             case FPOINTER:
13359               pic16_emitcode(";BUG!? ","%d",__LINE__);
13360                 l = one;
13361                 break;
13362             case PPOINTER:
13363               pic16_emitcode(";BUG!? ","%d",__LINE__);
13364                 l = "#0x03";
13365                 break;
13366
13367             case GPOINTER:
13368                 if (GPTRSIZE > AOP_SIZE(right)) {
13369                   // assume data pointer... THIS MIGHT BE WRONG!
13370                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13371                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13372                 } else {
13373                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13374                 }
13375               break;
13376               
13377             default:
13378                 /* this should never happen */
13379                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13380                        "got unknown pointer type");
13381                 exit(1);
13382             }
13383             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13384             goto release ;
13385         }
13386         
13387         /* just copy the pointers */
13388         size = AOP_SIZE(result);
13389         offset = 0 ;
13390         while (size--) {
13391             pic16_aopPut(AOP(result),
13392                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13393                    offset);
13394             offset++;
13395         }
13396         goto release ;
13397     }
13398     
13399
13400
13401     /* so we now know that the size of destination is greater
13402     than the size of the source.
13403     Now, if the next iCode is an operator then we might be
13404     able to optimize the operation without performing a cast.
13405     */
13406     if(genMixedOperation(ic))
13407       goto release;
13408
13409     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13410     
13411     /* we move to result for the size of source */
13412     size = AOP_SIZE(right);
13413     offset = 0 ;
13414     while (size--) {
13415       mov2f(AOP(result), AOP(right), offset);
13416       offset++;
13417     }
13418
13419     /* now depending on the sign of the destination */
13420     size = AOP_SIZE(result) - AOP_SIZE(right);
13421     /* if unsigned or not an integral type */
13422     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13423       while (size--)
13424         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13425     } else {
13426       /* we need to extend the sign :( */
13427
13428       if(size == 1) {
13429         /* Save one instruction of casting char to int */
13430         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13431         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13432         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13433       } else {
13434         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13435
13436         if(offset)
13437           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13438         else
13439           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13440         
13441         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13442
13443         while (size--)
13444           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13445       }
13446     }
13447
13448 release:
13449     pic16_freeAsmop(right,NULL,ic,TRUE);
13450     pic16_freeAsmop(result,NULL,ic,TRUE);
13451
13452 }
13453
13454 /*-----------------------------------------------------------------*/
13455 /* genDjnz - generate decrement & jump if not zero instrucion      */
13456 /*-----------------------------------------------------------------*/
13457 static int genDjnz (iCode *ic, iCode *ifx)
13458 {
13459     symbol *lbl, *lbl1;
13460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13461
13462     if (!ifx)
13463         return 0;
13464     
13465     /* if the if condition has a false label
13466        then we cannot save */
13467     if (IC_FALSE(ifx))
13468         return 0;
13469
13470     /* if the minus is not of the form 
13471        a = a - 1 */
13472     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13473         !IS_OP_LITERAL(IC_RIGHT(ic)))
13474         return 0;
13475
13476     if (operandLitValue(IC_RIGHT(ic)) != 1)
13477         return 0;
13478
13479     /* if the size of this greater than one then no
13480        saving */
13481     if (getSize(operandType(IC_RESULT(ic))) > 1)
13482         return 0;
13483
13484     /* otherwise we can save BIG */
13485     lbl = newiTempLabel(NULL);
13486     lbl1= newiTempLabel(NULL);
13487
13488     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13489     
13490     if (IS_AOP_PREG(IC_RESULT(ic))) {
13491         pic16_emitcode("dec","%s",
13492                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13494         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13495     } else {    
13496
13497
13498       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13499       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13500
13501       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13502       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13503
13504     }
13505     
13506     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13507     ifx->generated = 1;
13508     return 1;
13509 }
13510
13511 /*-----------------------------------------------------------------*/
13512 /* genReceive - generate code for a receive iCode                  */
13513 /*-----------------------------------------------------------------*/
13514 static void genReceive (iCode *ic)
13515 {    
13516
13517   FENTRY;
13518
13519 #if 0
13520   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13521         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13522 #endif
13523 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13524
13525   if (isOperandInFarSpace(IC_RESULT(ic))
13526       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13527           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13528
13529     int size = getSize(operandType(IC_RESULT(ic)));
13530     int offset =  pic16_fReturnSizePic - size;
13531
13532       assert( 0 );
13533       while (size--) {
13534         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13535                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13536                       offset++;
13537         }
13538
13539       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13540
13541       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13542       size = AOP_SIZE(IC_RESULT(ic));
13543       offset = 0;
13544       while (size--) {
13545         pic16_emitcode ("pop","acc");
13546         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13547       }
13548   } else {
13549     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13550     _G.accInUse++;
13551     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13552     _G.accInUse--;
13553
13554     /* set pseudo stack pointer to where it should be - dw*/
13555     GpsuedoStkPtr = ic->parmBytes;
13556
13557     /* setting GpsuedoStkPtr has side effects here: */
13558     assignResultValue(IC_RESULT(ic), 0);
13559   }
13560
13561   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13562 }
13563
13564 /*-----------------------------------------------------------------*/
13565 /* genDummyRead - generate code for dummy read of volatiles        */
13566 /*-----------------------------------------------------------------*/
13567 static void
13568 genDummyRead (iCode * ic)
13569 {
13570   operand *op;
13571   int i;
13572
13573   op = IC_RIGHT(ic);
13574   if (op && IS_SYMOP(op)) {
13575     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13576       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13577       return;
13578     }
13579     pic16_aopOp (op, ic, FALSE);
13580     for (i=0; i < AOP_SIZE(op); i++) {
13581       // may need to protect this from the peepholer -- this is not nice but works...
13582       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13583       pic16_mov2w (AOP(op),i);
13584       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13585     } // for i
13586     pic16_freeAsmop (op, NULL, ic, TRUE);
13587   } else if (op) {
13588     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13589   } // if
13590 }
13591
13592 /*-----------------------------------------------------------------*/
13593 /* genpic16Code - generate code for pic16 based controllers        */
13594 /*-----------------------------------------------------------------*/
13595 /*
13596  * At this point, ralloc.c has gone through the iCode and attempted
13597  * to optimize in a way suitable for a PIC. Now we've got to generate
13598  * PIC instructions that correspond to the iCode.
13599  *
13600  * Once the instructions are generated, we'll pass through both the
13601  * peep hole optimizer and the pCode optimizer.
13602  *-----------------------------------------------------------------*/
13603
13604 void genpic16Code (iCode *lic)
13605 {
13606   iCode *ic;
13607   int cln = 0;
13608
13609     lineHead = lineCurr = NULL;
13610
13611     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13612     pic16_addpBlock(pb);
13613
13614 #if 0
13615     /* if debug information required */
13616     if (options.debug && currFunc) {
13617       if (currFunc) {
13618         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13619       }
13620     }
13621 #endif
13622
13623     for (ic = lic ; ic ; ic = ic->next ) {
13624
13625       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13626       if ( cln != ic->lineno ) {
13627         if ( options.debug ) {
13628           debugFile->writeCLine (ic);
13629         }
13630         
13631         if(!options.noCcodeInAsm) {
13632           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13633               printCLine(ic->filename, ic->lineno)));
13634         }
13635
13636         cln = ic->lineno ;
13637       }
13638         
13639       if(options.iCodeInAsm) {
13640         char *l;
13641
13642           /* insert here code to print iCode as comment */
13643           l = Safe_strdup(printILine(ic));
13644           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13645       }
13646         
13647       /* if the result is marked as
13648        * spilt and rematerializable or code for
13649        * this has already been generated then
13650        * do nothing */
13651       if (resultRemat(ic) || ic->generated ) 
13652         continue ;
13653         
13654       /* depending on the operation */
13655       switch (ic->op) {
13656         case '!' :
13657           pic16_genNot(ic);
13658           break;
13659             
13660         case '~' :
13661           pic16_genCpl(ic);
13662           break;
13663             
13664         case UNARYMINUS:
13665           genUminus (ic);
13666           break;
13667             
13668         case IPUSH:
13669           genIpush (ic);
13670           break;
13671             
13672         case IPOP:
13673           /* IPOP happens only when trying to restore a 
13674            * spilt live range, if there is an ifx statement
13675            * following this pop then the if statement might
13676            * be using some of the registers being popped which
13677            * would destroy the contents of the register so
13678            * we need to check for this condition and handle it */
13679            if (ic->next
13680              && ic->next->op == IFX
13681              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13682                genIfx (ic->next,ic);
13683           else
13684             genIpop (ic);
13685           break; 
13686             
13687         case CALL:
13688           genCall (ic);
13689           break;
13690             
13691         case PCALL:
13692           genPcall (ic);
13693           break;
13694             
13695         case FUNCTION:
13696           genFunction (ic);
13697           break;
13698             
13699         case ENDFUNCTION:
13700           genEndFunction (ic);
13701           break;
13702             
13703         case RETURN:
13704           genRet (ic);
13705           break;
13706             
13707         case LABEL:
13708           genLabel (ic);
13709           break;
13710             
13711         case GOTO:
13712           genGoto (ic);
13713           break;
13714             
13715         case '+' :
13716           pic16_genPlus (ic) ;
13717           break;
13718             
13719         case '-' :
13720           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13721             pic16_genMinus (ic);
13722           break;
13723
13724         case '*' :
13725           genMult (ic);
13726           break;
13727             
13728         case '/' :
13729           genDiv (ic) ;
13730           break;
13731             
13732         case '%' :
13733           genMod (ic);
13734           break;
13735             
13736         case '>' :
13737           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13738           break;
13739             
13740         case '<' :
13741           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13742           break;
13743             
13744         case LE_OP:
13745         case GE_OP:
13746         case NE_OP:
13747           /* note these two are xlated by algebraic equivalence
13748            * during parsing SDCC.y */
13749           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13750             "got '>=' or '<=' shouldn't have come here");
13751           break;
13752
13753         case EQ_OP:
13754           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13755           break;            
13756             
13757         case AND_OP:
13758           genAndOp (ic);
13759           break;
13760             
13761         case OR_OP:
13762           genOrOp (ic);
13763           break;
13764             
13765         case '^' :
13766           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13767           break;
13768             
13769         case '|' :
13770           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13771           break;
13772             
13773         case BITWISEAND:
13774           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13775           break;
13776             
13777         case INLINEASM:
13778           genInline (ic);
13779           break;
13780             
13781         case RRC:
13782           genRRC (ic);
13783           break;
13784             
13785         case RLC:
13786           genRLC (ic);
13787           break;
13788             
13789         case GETHBIT:
13790           genGetHbit (ic);
13791           break;
13792             
13793         case LEFT_OP:
13794           genLeftShift (ic);
13795           break;
13796             
13797         case RIGHT_OP:
13798           genRightShift (ic);
13799           break;
13800             
13801         case GET_VALUE_AT_ADDRESS:
13802           genPointerGet(ic);
13803           break;
13804             
13805         case '=' :
13806           if (POINTER_SET(ic))
13807             genPointerSet(ic);
13808           else
13809             genAssign(ic);
13810           break;
13811             
13812         case IFX:
13813           genIfx (ic,NULL);
13814           break;
13815             
13816         case ADDRESS_OF:
13817           genAddrOf (ic);
13818           break;
13819             
13820         case JUMPTABLE:
13821           genJumpTab (ic);
13822           break;
13823             
13824         case CAST:
13825           genCast (ic);
13826           break;
13827             
13828         case RECEIVE:
13829           genReceive(ic);
13830           break;
13831             
13832         case SEND:
13833           addSet(&_G.sendSet,ic);
13834           break;
13835
13836         case DUMMY_READ_VOLATILE:
13837           genDummyRead (ic);
13838           break;
13839
13840         default :
13841           ic = ic;
13842       }
13843     }
13844
13845
13846     /* now we are ready to call the
13847        peep hole optimizer */
13848     if (!options.nopeep)
13849       peepHole (&lineHead);
13850
13851     /* now do the actual printing */
13852     printLine (lineHead, codeOutFile);
13853
13854 #ifdef PCODE_DEBUG
13855     DFPRINTF((stderr,"printing pBlock\n\n"));
13856     pic16_printpBlock(stdout,pb);
13857 #endif
13858
13859     return;
13860 }
13861