* src/pic/gen.c: handle FPOINTERS like POINTERS everywhere
[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   Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
65
66 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
67 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
68 void pic16_genMult8X8_8 (operand *, operand *,operand *);
69 void pic16_genMult16X16_16(operand *, operand *, operand *);
70 void pic16_genMult32X32_32(operand *, operand *, operand *);
71 pCode *pic16_AssembleLine(char *line, int peeps);
72 extern void pic16_printpBlock(FILE *of, pBlock *pb);
73 static asmop *newAsmop (short type);
74 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
75 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
76 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
77 static pCodeOp *pic16_popRegFromIdx(int rIdx);
78
79 //static int aopIdx (asmop *aop, int offset);
80
81 int pic16_labelOffset=0;
82 extern int pic16_debug_verbose;
83 #if !(USE_GENERIC_SIGNED_SHIFT)
84 static int optimized_for_speed = 0;
85 #endif
86 /*
87   hack hack
88
89 */
90
91 extern set *externs;
92
93 /* max_key keeps track of the largest label number used in 
94    a function. This is then used to adjust the label offset
95    for the next function.
96 */
97 static int max_key=0;
98 static int GpsuedoStkPtr=0;
99
100 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
101
102 unsigned int pic16aopLiteral (value *val, int offset);
103 const char *pic16_AopType(short type);
104 static iCode *ifxForOp ( operand *op, iCode *ic );
105
106 void pic16_pushpCodeOp(pCodeOp *pcop);
107 void pic16_poppCodeOp(pCodeOp *pcop);
108
109 static bool is_LitOp(operand *op);
110 static bool is_LitAOp(asmop *aop);
111
112
113 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
114
115 /* set the following macro to 1 to enable passing the
116  * first byte of functions parameters via WREG */
117 #define USE_WREG_IN_FUNC_PARAMS 0
118
119
120 /* this is the down and dirty file with all kinds of 
121    kludgy & hacky stuff. This is what it is all about
122    CODE GENERATION for a specific MCU . some of the
123    routines may be reusable, will have to see */
124
125 static char *zero = "#0x00";
126 static char *one  = "#0x01";
127 //static char *spname = "sp";
128
129
130 /*
131  * Function return value policy (MSB-->LSB):
132  *  8 bits      -> WREG
133  * 16 bits      -> PRODL:WREG
134  * 24 bits      -> PRODH:PRODL:WREG
135  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
136  * >32 bits     -> on stack, and FSR0 points to the beginning
137  *
138  */
139  
140
141 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
142 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
143 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
144 static char **fReturn = fReturnpic16;
145
146 static char *accUse[] = {"WREG"};
147
148 //static short rbank = -1;
149
150 static struct {
151     short r0Pushed;
152     short r1Pushed;
153     short fsr0Pushed;
154     short accInUse;
155     short inLine;
156     short debugLine;
157     short nRegsSaved;
158     short ipushRegs;
159     set *sendSet;
160     set *stackRegSet;
161     int usefastretfie;
162     bitVect *fregsUsed;                 /* registers used in function */
163     bitVect *sregsAlloc;
164     set *sregsAllocSet;                 /* registers used to store stack variables */
165     int stack_lat;                      /* stack offset latency */
166     int resDirect;
167     int useWreg;                        /* flag when WREG is used to pass function parameter */
168 } _G;
169
170 extern int pic16_ptrRegReq ;
171 extern int pic16_nRegs;
172 extern FILE *codeOutFile;
173 //static void saverbank (int, iCode *,bool);
174
175 static lineNode *lineHead = NULL;
176 static lineNode *lineCurr = NULL;
177
178 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
179 0xE0, 0xC0, 0x80, 0x00};
180 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
181 0x07, 0x03, 0x01, 0x00};
182
183 static  pBlock *pb;
184
185 /*-----------------------------------------------------------------*/
186 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
187 /*                 exponent of 2 is returned, otherwise -1 is      */
188 /*                 returned.                                       */
189 /* note that this is similar to the function `powof2' in SDCCsymt  */
190 /* if(n == 2^y)                                                    */
191 /*   return y;                                                     */
192 /* return -1;                                                      */
193 /*-----------------------------------------------------------------*/
194 int pic16_my_powof2 (unsigned long num)
195 {
196   if(num) {
197     if( (num & (num-1)) == 0) {
198       int nshifts = -1;
199       while(num) {
200         num>>=1;
201         nshifts++;
202       }
203       return nshifts;
204     }
205   }
206
207   return -1;
208 }
209
210 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
211 {
212   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
213                        line_no,
214                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
215                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
216                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
217                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
218                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
219                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
220                        ((result) ? AOP_SIZE(result) : 0));
221 }
222
223 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
224 {
225
226   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
227                        line_no,
228                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
229                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
230                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
231                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
232                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
233                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
234
235 }
236
237 void pic16_emitpcomment (char *fmt, ...)
238 {
239     va_list ap;
240     char lb[INITIAL_INLINEASM];  
241     unsigned char *lbp = lb;
242
243     va_start(ap,fmt);   
244
245     lb[0] = ';';
246     vsprintf(lb+1,fmt,ap);
247
248     while (isspace(*lbp)) lbp++;
249
250     if (lbp && *lbp) 
251         lineCurr = (lineCurr ?
252                     connectLine(lineCurr,newLineNode(lb)) :
253                     (lineHead = newLineNode(lb)));
254     lineCurr->isInline = _G.inLine;
255     lineCurr->isDebug  = _G.debugLine;
256
257     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
258     va_end(ap);
259
260 //      fprintf(stderr, "%s\n", lb);
261 }
262
263 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
264 {
265     va_list ap;
266     char lb[INITIAL_INLINEASM];  
267     unsigned char *lbp = lb;
268
269     if(!pic16_debug_verbose)
270       return;
271
272     va_start(ap,fmt);   
273
274     if (inst && *inst) {
275         if (fmt && *fmt)
276             sprintf(lb,"%s\t",inst);
277         else
278             sprintf(lb,"%s",inst);
279         vsprintf(lb+(strlen(lb)),fmt,ap);
280     }  else
281         vsprintf(lb,fmt,ap);
282
283     while (isspace(*lbp)) lbp++;
284
285     if (lbp && *lbp) 
286         lineCurr = (lineCurr ?
287                     connectLine(lineCurr,newLineNode(lb)) :
288                     (lineHead = newLineNode(lb)));
289     lineCurr->isInline = _G.inLine;
290     lineCurr->isDebug  = _G.debugLine;
291
292     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
293     va_end(ap);
294
295 //      fprintf(stderr, "%s\n", lb);
296 }
297
298
299
300 void pic16_emitpLabel(int key)
301 {
302   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
303 }
304
305 void pic16_emitpLabelFORCE(int key)
306 {
307   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
308 }
309
310 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
311  * NEVER call pic16_emitpcode_real directly, please... */
312 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
313 {
314
315   if(pcop)
316     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
317   else
318     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
319 }
320
321 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
322 {
323   if(pcop)
324     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
325   else
326     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
327 }
328   
329 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
330 {
331
332   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
333
334 }
335
336
337 #if 1
338 #define pic16_emitcode  DEBUGpic16_emitcode
339 #else
340 /*-----------------------------------------------------------------*/
341 /* pic16_emitcode - writes the code into a file : for now it is simple    */
342 /*-----------------------------------------------------------------*/
343 void pic16_emitcode (char *inst,char *fmt, ...)
344 {
345     va_list ap;
346     char lb[INITIAL_INLINEASM];  
347     unsigned char *lbp = lb;
348
349     va_start(ap,fmt);   
350
351     if (inst && *inst) {
352         if (fmt && *fmt)
353             sprintf(lb,"%s\t",inst);
354         else
355             sprintf(lb,"%s",inst);
356         vsprintf(lb+(strlen(lb)),fmt,ap);
357     }  else
358         vsprintf(lb,fmt,ap);
359
360     while (isspace(*lbp)) lbp++;
361
362     if (lbp && *lbp) 
363         lineCurr = (lineCurr ?
364                     connectLine(lineCurr,newLineNode(lb)) :
365                     (lineHead = newLineNode(lb)));
366     lineCurr->isInline = _G.inLine;
367     lineCurr->isDebug  = _G.debugLine;
368
369 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
370
371 //    if(pic16_debug_verbose)
372 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
373
374     va_end(ap);
375 }
376 #endif
377
378
379 /*-----------------------------------------------------------------*/
380 /* pic16_emitDebuggerSymbol - associate the current code location  */
381 /*   with a debugger symbol                                        */
382 /*-----------------------------------------------------------------*/
383 void
384 pic16_emitDebuggerSymbol (char * debugSym)
385 {
386   _G.debugLine = 1;
387   pic16_emitcode (";", "%s ==.", debugSym);
388   _G.debugLine = 0;
389 }
390
391
392 /*-----------------------------------------------------------------*/
393 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
394 /*-----------------------------------------------------------------*/
395 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
396 {
397 //    bool r0iu = FALSE , r1iu = FALSE;
398 //    bool r0ou = FALSE , r1ou = FALSE;
399     bool fsr0iu = FALSE, fsr0ou;
400     bool fsr2iu = FALSE, fsr2ou;
401     
402     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
403
404     
405     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
406     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
407     
408     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
409     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
410
411     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
412         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
413         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
414     }
415
416     if(!fsr0iu && !fsr0ou) {
417         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
418         (*aopp)->type = AOP_FSR0;
419
420         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
421         
422       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
423     }
424
425 #if 0
426     /* no usage of FSR2 */
427     if(!fsr2iu && !fsr2ou) {
428         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
429         (*aopp)->type = AOP_FSR2;
430
431       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
432     }
433 #endif
434         
435     /* now we know they both have usage */
436     /* if fsr0 not used in this instruction */
437     if (!fsr0iu) {
438         if (!_G.fsr0Pushed) {
439                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
440                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
441                 _G.fsr0Pushed++;
442         }
443
444         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
445         (*aopp)->type = AOP_FSR0;
446
447 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
448
449       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
450     }
451         
452
453     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
454     assert( 0 );
455
456     return NULL;
457 #if 0
458     /* the logic: if r0 & r1 used in the instruction
459     then we are in trouble otherwise */
460
461     /* first check if r0 & r1 are used by this
462     instruction, in which case we are in trouble */
463     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
464         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
465     {
466         goto endOfWorld;      
467     }
468
469     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
470     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
471
472     /* if no usage of r0 then return it */
473     if (!r0iu && !r0ou) {
474         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
475         (*aopp)->type = AOP_R0; 
476         
477         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
478     }
479
480     /* if no usage of r1 then return it */
481     if (!r1iu && !r1ou) {
482         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
483         (*aopp)->type = AOP_R1;
484
485         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
486     }    
487
488     /* now we know they both have usage */
489     /* if r0 not used in this instruction */
490     if (!r0iu) {
491         /* push it if not already pushed */
492         if (!_G.r0Pushed) {
493           //pic16_emitcode ("push","%s",
494           //          pic16_regWithIdx(R0_IDX)->dname);
495             _G.r0Pushed++ ;
496         }
497         
498         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
499         (*aopp)->type = AOP_R0;
500
501         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
502     }
503
504     /* if r1 not used then */
505
506     if (!r1iu) {
507         /* push it if not already pushed */
508         if (!_G.r1Pushed) {
509           //pic16_emitcode ("push","%s",
510           //          pic16_regWithIdx(R1_IDX)->dname);
511             _G.r1Pushed++ ;
512         }
513         
514         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
515         (*aopp)->type = AOP_R1;
516         return pic16_regWithIdx(R1_IDX);
517     }
518
519 endOfWorld :
520     /* I said end of world but not quite end of world yet */
521     /* if this is a result then we can push it on the stack*/
522     if (result) {
523         (*aopp)->type = AOP_STK;    
524         return NULL;
525     }
526
527     /* other wise this is true end of the world */
528     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
529            "getFreePtr should never reach here");
530     exit(0);
531 #endif
532 }
533
534 /*-----------------------------------------------------------------*/
535 /* newAsmop - creates a new asmOp                                  */
536 /*-----------------------------------------------------------------*/
537 static asmop *newAsmop (short type)
538 {
539     asmop *aop;
540
541     aop = Safe_calloc(1,sizeof(asmop));
542     aop->type = type;
543     return aop;
544 }
545
546 static void genSetDPTR(int n)
547 {
548     if (!n)
549     {
550         pic16_emitcode(";", "Select standard DPTR");
551         pic16_emitcode("mov", "dps, #0x00");
552     }
553     else
554     {
555         pic16_emitcode(";", "Select alternate DPTR");
556         pic16_emitcode("mov", "dps, #0x01");
557     }
558 }
559
560 /*-----------------------------------------------------------------*/
561 /* resolveIfx - converts an iCode ifx into a form more useful for  */
562 /*              generating code                                    */
563 /*-----------------------------------------------------------------*/
564 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
565 {
566   FENTRY2;
567   
568 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
569
570   if(!resIfx) 
571     return;
572
573
574   resIfx->condition = 1;    /* assume that the ifx is true */
575   resIfx->generated = 0;    /* indicate that the ifx has not been used */
576
577   if(!ifx) {
578     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
579
580 #if 1
581     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
582                         __FUNCTION__,__LINE__,resIfx->lbl->key);
583 #endif
584
585   } else {
586     if(IC_TRUE(ifx)) {
587       resIfx->lbl = IC_TRUE(ifx);
588     } else {
589       resIfx->lbl = IC_FALSE(ifx);
590       resIfx->condition = 0;
591     }
592
593 #if 1
594     if(IC_TRUE(ifx)) 
595       DEBUGpic16_emitcode("; +++","ifx true is non-null");
596     else
597       DEBUGpic16_emitcode("; +++","ifx true is null");
598     if(IC_FALSE(ifx)) 
599       DEBUGpic16_emitcode("; +++","ifx false is non-null");
600     else
601       DEBUGpic16_emitcode("; +++","ifx false is null");
602 #endif
603   }
604
605   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
606
607 }
608 #if 0
609 /*-----------------------------------------------------------------*/
610 /* pointerCode - returns the code for a pointer type               */
611 /*-----------------------------------------------------------------*/
612 static int pointerCode (sym_link *etype)
613 {
614
615     return PTR_TYPE(SPEC_OCLS(etype));
616
617 }
618 #endif
619
620 /*-----------------------------------------------------------------*/
621 /* aopForSym - for a true symbol                                   */
622 /*-----------------------------------------------------------------*/
623 static asmop *aopForSym (iCode *ic, operand *op, bool result)
624 {
625     symbol *sym=OP_SYMBOL(op);
626     asmop *aop;
627     memmap *space= SPEC_OCLS(sym->etype);
628
629     FENTRY2;
630     
631     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
632     
633 //    sym = OP_SYMBOL(op);
634
635     /* if already has one */
636     if (sym->aop) {
637             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
638         return sym->aop;
639     }
640
641 #if 0
642     /* if symbol was initially placed onStack then we must re-place it
643      * to direct memory, since pic16 does not have a specific stack */
644     if(sym->onStack) {
645         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
646     }
647 #endif
648
649
650 #if 0
651     if(sym->iaccess) {
652       if(space->paged) {
653         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
654
655         sym->aop = aop = newAsmop (AOP_PAGED);
656         aop->aopu.aop_dir = sym->rname ;
657         aop->size = getSize(sym->type);
658         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
659         pic16_allocDirReg( IC_LEFT(ic) );
660         return aop;
661       }
662       assert( 0 );
663     }
664 #endif
665     
666 #if 1
667     /* assign depending on the storage class */
668     /* if it is on the stack or indirectly addressable */
669     /* space we need to assign either r0 or r1 to it   */    
670     if (sym->onStack)   // || sym->iaccess)
671     {
672       pCodeOp *pcop[4];
673       int i;
674       
675         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
676                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
677         
678         /* acquire a temporary register -- it is saved in function */
679
680         sym->aop = aop = newAsmop(AOP_STA);
681         aop->aopu.stk.stk = sym->stack;
682         aop->size = getSize(sym->type);
683
684
685         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
686         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
687           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
688 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
689           
690           for(i=0;i<aop->size;i++)
691             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
692             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
693         } else
694         if(1 && ic->op == SEND) {
695
696           /* if SEND do the send here */
697           _G.resDirect = 1;
698         } else {
699           for(i=0;i<aop->size;i++) {
700             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
701             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
702           }
703         }
704
705
706 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
707
708 #if 1
709         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
710
711         // we do not need to load the value if it is to be defined...
712         if (result) return aop;
713
714         if(_G.accInUse) {
715                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
716         }
717         
718         for(i=0;i<aop->size;i++) {
719
720           /* initialise for stack access via frame pointer */
721           // operands on stack are accessible via "FSR2 + index" with index
722           // starting at 2 for arguments and growing from 0 downwards for
723           // local variables (index == 0 is not assigned so we add one here)
724           {
725             int soffs = sym->stack;
726             if (soffs <= 0) {
727               assert (soffs < 0);
728               soffs++;
729             } // if
730
731             if(1 && ic->op == SEND) {
732               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
733               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
734                     pic16_popCopyReg( pic16_frame_plusw ),
735                     pic16_popCopyReg(pic16_stack_postdec )));
736             } else {
737               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
738               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
739                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
740             }
741           }
742         }
743         
744         if(_G.accInUse) {
745                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
746         }
747         
748         return (aop);
749 #endif
750
751 #if 0
752         /* now assign the address of the variable to 
753         the pointer register */
754         if (aop->type != AOP_STK) {
755
756             if (sym->onStack) {
757                     if ( _G.accInUse )
758                         pic16_emitcode("push","acc");
759
760                     pic16_emitcode("mov","a,_bp");
761                     pic16_emitcode("add","a,#0x%02x",
762                              ((sym->stack < 0) ?
763                               ((char)(sym->stack - _G.nRegsSaved )) :
764                               ((char)sym->stack)) & 0xff);
765                     pic16_emitcode("mov","%s,a",
766                              aop->aopu.aop_ptr->name);
767
768                     if ( _G.accInUse )
769                         pic16_emitcode("pop","acc");
770             } else
771                 pic16_emitcode("mov","%s,#%s",
772                          aop->aopu.aop_ptr->name,
773                          sym->rname);
774             aop->paged = space->paged;
775         } else
776             aop->aopu.aop_stk = sym->stack;
777         return aop;
778 #endif
779
780     }
781 #endif
782
783 #if 0
784     if (sym->onStack && options.stack10bit)
785     {
786         /* It's on the 10 bit stack, which is located in
787          * far data space.
788          */
789          
790       //DEBUGpic16_emitcode(";","%d",__LINE__);
791
792         if ( _G.accInUse )
793                 pic16_emitcode("push","acc");
794
795         pic16_emitcode("mov","a,_bp");
796         pic16_emitcode("add","a,#0x%02x",
797                  ((sym->stack < 0) ?
798                    ((char)(sym->stack - _G.nRegsSaved )) :
799                    ((char)sym->stack)) & 0xff);
800         
801         genSetDPTR(1);
802         pic16_emitcode ("mov","dpx1,#0x40");
803         pic16_emitcode ("mov","dph1,#0x00");
804         pic16_emitcode ("mov","dpl1, a");
805         genSetDPTR(0);
806         
807         if ( _G.accInUse )
808             pic16_emitcode("pop","acc");
809             
810         sym->aop = aop = newAsmop(AOP_DPTR2);
811         aop->size = getSize(sym->type); 
812         return aop;
813     }
814 #endif
815
816 #if 1
817     /* special case for a function */
818     if (IS_FUNC(sym->type)) {   
819         sym->aop = aop = newAsmop(AOP_PCODE);
820         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
821         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
822         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
823         PCOI(aop->aopu.pcop)->index = 0;
824         aop->size = FPTRSIZE; 
825         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
826         return aop;
827     }
828 #endif
829
830
831
832     //DEBUGpic16_emitcode(";","%d",__LINE__);
833     /* if in bit space */
834     if (IN_BITSPACE(space)) {
835         sym->aop = aop = newAsmop (AOP_CRY);
836         aop->aopu.aop_dir = sym->rname ;
837         aop->size = getSize(sym->type);
838         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
839         return aop;
840     }
841     /* if it is in direct space */
842     if (IN_DIRSPACE(space)) {
843         sym->aop = aop = newAsmop (AOP_DIR);
844         aop->aopu.aop_dir = sym->rname ;
845         aop->size = getSize(sym->type);
846         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
847         pic16_allocDirReg( IC_LEFT(ic) );
848         return aop;
849     }
850
851
852     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
853         sym->aop = aop = newAsmop (AOP_DIR);
854         aop->aopu.aop_dir = sym->rname ;
855         aop->size = getSize(sym->type);
856         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
857         pic16_allocDirReg( IC_LEFT(ic) );
858         return aop;
859     }
860
861
862     /* only remaining is far space */
863     sym->aop = aop = newAsmop(AOP_PCODE);
864
865 /* change the next if to 1 to revert to good old immediate code */
866         if(IN_CODESPACE(space)) {
867                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
868                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
869                 PCOI(aop->aopu.pcop)->index = 0;
870         } else {
871                 /* try to allocate via direct register */
872                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
873 //              aop->size = getSize( sym->type );
874         }
875
876         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
877                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
878
879 #if 0
880         if(!pic16_allocDirReg (IC_LEFT(ic)))
881                 return NULL;
882 #endif
883
884         if(IN_DIRSPACE( space ))
885                 aop->size = PTRSIZE;
886         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
887                 aop->size = FPTRSIZE;
888         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
889         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
890         else if(sym->onStack) {
891                 aop->size = PTRSIZE;
892         } else {
893           if(SPEC_SCLS(sym->etype) == S_PDATA) {
894             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
895             aop->size = FPTRSIZE;
896           } else
897                 assert( 0 );
898         }
899
900     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
901
902     /* if it is in code space */
903     if (IN_CODESPACE(space))
904         aop->code = 1;
905
906     return aop;     
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* aopForRemat - rematerialzes an object                           */
911 /*-----------------------------------------------------------------*/
912 static asmop *aopForRemat (operand *op) // x symbol *sym)
913 {
914   symbol *sym = OP_SYMBOL(op);
915   operand *refop;
916   iCode *ic = NULL, *oldic;
917   asmop *aop = newAsmop(AOP_PCODE);
918   int val = 0;
919   int offset = 0;
920   int viaimmd=0;
921
922     FENTRY2;
923     
924         ic = sym->rematiCode;
925
926         if(IS_OP_POINTER(op)) {
927                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
928         }
929
930         for (;;) {
931                 oldic = ic;
932
933 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
934         
935                 if (ic->op == '+') {
936                         val += (int) operandLitValue(IC_RIGHT(ic));
937                 } else if (ic->op == '-') {
938                         val -= (int) operandLitValue(IC_RIGHT(ic));
939                 } else
940                         break;
941                 
942                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
943         }
944
945         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
946         refop = IC_LEFT(ic);
947
948         if(!op->isaddr)viaimmd++; else viaimmd=0;
949                 
950 /* set the following if to 1 to revert to good old immediate code */
951         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
952                 || viaimmd) {
953
954                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
955
956                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
957
958 #if 0
959                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
960 #else
961                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
962 #endif
963
964                 PCOI(aop->aopu.pcop)->index = val;
965                 
966                 aop->size = getSize( sym->type );
967         } else {
968                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
969
970                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
971                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
972
973                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
974         }
975
976
977         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
978                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
979 #if 0
980                 val, IS_PTR_CONST(operandType(op)));
981 #else
982                 val, IS_CODEPTR(operandType(op)));
983 #endif
984
985 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
986
987         pic16_allocDirReg (IC_LEFT(ic));
988
989         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
990                 aop->code = 1;
991
992   return aop;        
993 }
994
995 #if 0
996 static int aopIdx (asmop *aop, int offset)
997 {
998   if(!aop)
999     return -1;
1000
1001   if(aop->type !=  AOP_REG)
1002     return -2;
1003         
1004   return aop->aopu.aop_reg[offset]->rIdx;
1005
1006 }
1007 #endif
1008
1009 /*-----------------------------------------------------------------*/
1010 /* regsInCommon - two operands have some registers in common       */
1011 /*-----------------------------------------------------------------*/
1012 static bool regsInCommon (operand *op1, operand *op2)
1013 {
1014     symbol *sym1, *sym2;
1015     int i;
1016
1017     /* if they have registers in common */
1018     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1019         return FALSE ;
1020
1021     sym1 = OP_SYMBOL(op1);
1022     sym2 = OP_SYMBOL(op2);
1023
1024     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1025         return FALSE ;
1026
1027     for (i = 0 ; i < sym1->nRegs ; i++) {
1028         int j;
1029         if (!sym1->regs[i])
1030             continue ;
1031
1032         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1033             if (!sym2->regs[j])
1034                 continue ;
1035
1036             if (sym2->regs[j] == sym1->regs[i])
1037                 return TRUE ;
1038         }
1039     }
1040
1041     return FALSE ;
1042 }
1043
1044 /*-----------------------------------------------------------------*/
1045 /* operandsEqu - equivalent                                        */
1046 /*-----------------------------------------------------------------*/
1047 static bool operandsEqu ( operand *op1, operand *op2)
1048 {
1049     symbol *sym1, *sym2;
1050
1051     /* if they not symbols */
1052     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1053         return FALSE;
1054
1055     sym1 = OP_SYMBOL(op1);
1056     sym2 = OP_SYMBOL(op2);
1057
1058     /* if both are itemps & one is spilt
1059        and the other is not then false */
1060     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1061         sym1->isspilt != sym2->isspilt )
1062         return FALSE ;
1063
1064     /* if they are the same */
1065     if (sym1 == sym2)
1066         return TRUE ;
1067
1068     if (sym1->rname[0] && sym2->rname[0]
1069         && strcmp (sym1->rname, sym2->rname) == 0)
1070         return TRUE;
1071
1072
1073     /* if left is a tmp & right is not */
1074     if (IS_ITEMP(op1)  && 
1075         !IS_ITEMP(op2) &&
1076         sym1->isspilt  &&
1077         (sym1->usl.spillLoc == sym2))
1078         return TRUE;
1079
1080     if (IS_ITEMP(op2)  && 
1081         !IS_ITEMP(op1) &&
1082         sym2->isspilt  &&
1083         sym1->level > 0 &&
1084         (sym2->usl.spillLoc == sym1))
1085         return TRUE ;
1086
1087     return FALSE ;
1088 }
1089
1090 /*-----------------------------------------------------------------*/
1091 /* pic16_sameRegs - two asmops have the same registers                   */
1092 /*-----------------------------------------------------------------*/
1093 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1094 {
1095     int i;
1096
1097     if (aop1 == aop2)
1098         return TRUE ;
1099
1100     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1101                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1102
1103     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1104
1105     if (aop1->type != AOP_REG ||
1106         aop2->type != AOP_REG )
1107         return FALSE ;
1108
1109     /* This is a bit too restrictive if one is a subset of the other...
1110     if (aop1->size != aop2->size )
1111         return FALSE ;
1112     */
1113
1114     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1115 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1116
1117 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1118         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1119             return FALSE ;
1120     }
1121
1122     return TRUE ;
1123 }
1124
1125 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1126 {
1127     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1128                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1129
1130     if(aop1 == aop2)return TRUE;
1131     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1132       
1133       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1134     
1135   return TRUE;
1136 }
1137
1138
1139 /*-----------------------------------------------------------------*/
1140 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1141 /*-----------------------------------------------------------------*/
1142 void pic16_aopOp (operand *op, iCode *ic, bool result)
1143 {
1144     asmop *aop;
1145     symbol *sym;
1146     int i;
1147
1148     if (!op)
1149         return ;
1150
1151     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1152
1153     /* if this a literal */
1154     if (IS_OP_LITERAL(op)) {
1155         op->aop = aop = newAsmop(AOP_LIT);
1156         aop->aopu.aop_lit = op->operand.valOperand;
1157         aop->size = getSize(operandType(op));
1158         return;
1159     }
1160
1161     {
1162       sym_link *type = operandType(op);
1163 #if 0
1164       if(IS_PTR_CONST(type))
1165 #else
1166       if(IS_CODEPTR(type))
1167 #endif
1168         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1169     }
1170
1171     /* if already has a asmop then continue */
1172     if (op->aop)
1173         return ;
1174
1175     /* if the underlying symbol has a aop */
1176     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1177       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1178         op->aop = OP_SYMBOL(op)->aop;
1179         return;
1180     }
1181
1182     /* if this is a true symbol */
1183     if (IS_TRUE_SYMOP(op)) {    
1184         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1185       op->aop = aopForSym(ic, op, result);
1186       return ;
1187     }
1188
1189     /* this is a temporary : this has
1190     only four choices :
1191     a) register
1192     b) spillocation
1193     c) rematerialize 
1194     d) conditional   
1195     e) can be a return use only */
1196
1197     sym = OP_SYMBOL(op);
1198
1199     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1200     /* if the type is a conditional */
1201     if (sym->regType == REG_CND) {
1202         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1203         aop->size = 0;
1204         return;
1205     }
1206
1207     /* if it is spilt then two situations
1208     a) is rematerialize 
1209     b) has a spill location */
1210     if (sym->isspilt || sym->nRegs == 0) {
1211
1212 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1213       DEBUGpic16_emitcode(";","%d",__LINE__);
1214         /* rematerialize it NOW */
1215         if (sym->remat) {
1216
1217             sym->aop = op->aop = aop = aopForRemat (op);
1218 //            aop->size = getSize(sym->type);
1219 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1220             return;
1221         }
1222
1223 #if 1
1224         if (sym->accuse) {
1225             int i;
1226             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1227             aop->size = getSize(sym->type);
1228             for ( i = 0 ; i < 1 ; i++ ) {
1229                 aop->aopu.aop_str[i] = accUse[i];
1230 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1231             }
1232             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1233             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1234             return;  
1235         }
1236 #endif
1237
1238 #if 1
1239         if (sym->ruonly) {
1240           /*
1241           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1242           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1243           //pic16_allocDirReg (IC_LEFT(ic));
1244           aop->size = getSize(sym->type);
1245           */
1246
1247           unsigned i;
1248
1249           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1250           aop->size = getSize(sym->type);
1251           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1252             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1253
1254           DEBUGpic16_emitcode(";","%d",__LINE__);
1255           return;
1256         }
1257 #endif
1258         /* else spill location  */
1259         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1260             /* force a new aop if sizes differ */
1261             sym->usl.spillLoc->aop = NULL;
1262         }
1263
1264 #if 0
1265         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1266                             __FUNCTION__,__LINE__,
1267                             sym->usl.spillLoc->rname,
1268                             sym->rname, sym->usl.spillLoc->offset);
1269 #endif
1270
1271         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1272         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1273         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1274           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1275                                                   getSize(sym->type), 
1276                                                   sym->usl.spillLoc->offset, op);
1277         } else {
1278           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1279           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1280           assert (getSize(sym->type) <= 1);
1281           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1282         }
1283         aop->size = getSize(sym->type);
1284
1285         return;
1286     }
1287
1288     {
1289       sym_link *type = operandType(op);
1290 #if 0
1291       if(IS_PTR_CONST(type)) 
1292 #else
1293       if(IS_CODEPTR(type)) 
1294 #endif
1295         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1296     }
1297
1298     /* must be in a register */
1299     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1300     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1301     aop->size = sym->nRegs;
1302     for ( i = 0 ; i < sym->nRegs ;i++)
1303         aop->aopu.aop_reg[i] = sym->regs[i];
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* pic16_freeAsmop - free up the asmop given to an operand               */
1308 /*----------------------------------------------------------------*/
1309 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1310 {   
1311     asmop *aop ;
1312
1313     if (!op)
1314         aop = aaop;
1315     else 
1316         aop = op->aop;
1317
1318     if (!aop)
1319         return ;
1320
1321     if (aop->freed)
1322         goto dealloc; 
1323
1324     aop->freed = 1;
1325
1326     /* depending on the asmop type only three cases need work AOP_RO
1327        , AOP_R1 && AOP_STK */
1328 #if 1
1329     switch (aop->type) {
1330         case AOP_FSR0 :
1331             if (_G.fsr0Pushed ) {
1332                 if (pop) {
1333                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1334                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1335 //                    pic16_emitcode ("pop","ar0");
1336                     _G.fsr0Pushed--;
1337                 }
1338             }
1339             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1340             break;
1341
1342         case AOP_FSR2 :
1343             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1344             break;
1345
1346         case AOP_R0 :
1347             if (_G.r0Pushed ) {
1348                 if (pop) {
1349                     pic16_emitcode ("pop","ar0");     
1350                     _G.r0Pushed--;
1351                 }
1352             }
1353             bitVectUnSetBit(ic->rUsed,R0_IDX);
1354             break;
1355
1356         case AOP_R1 :
1357             if (_G.r1Pushed ) {
1358                 if (pop) {
1359                     pic16_emitcode ("pop","ar1");
1360                     _G.r1Pushed--;
1361                 }
1362             }
1363             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1364             break;
1365
1366         case AOP_STA:
1367           {
1368             int i;
1369
1370               /* we must store the result on stack */
1371               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1372                 // operands on stack are accessible via "FSR2 + index" with index
1373                 // starting at 2 for arguments and growing from 0 downwards for
1374                 // local variables (index == 0 is not assigned so we add one here)
1375                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1376                 if (soffs <= 0) {
1377                   assert (soffs < 0);
1378                   soffs++;
1379                 } // if
1380                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1381                 for(i=0;i<aop->size;i++) {
1382                   /* initialise for stack access via frame pointer */
1383                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1384                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1385                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1386                 }
1387         
1388                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1389               }
1390
1391               if(!_G.resDirect) {
1392                 for(i=0;i<aop->size;i++) {
1393                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1394
1395                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1396                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1397                 }
1398                   
1399               }
1400               _G.resDirect = 0;
1401           }
1402           break;
1403 #if 0
1404         case AOP_STK :
1405         {
1406             int sz = aop->size;    
1407             int stk = aop->aopu.aop_stk + aop->size;
1408             bitVectUnSetBit(ic->rUsed,R0_IDX);
1409             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1410
1411             getFreePtr(ic,&aop,FALSE);
1412             
1413             if (options.stack10bit)
1414             {
1415                 /* I'm not sure what to do here yet... */
1416                 /* #STUB */
1417                 fprintf(stderr, 
1418                         "*** Warning: probably generating bad code for "
1419                         "10 bit stack mode.\n");
1420             }
1421             
1422             if (stk) {
1423                 pic16_emitcode ("mov","a,_bp");
1424                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1425                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1426             } else {
1427                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1428             }
1429
1430             while (sz--) {
1431                 pic16_emitcode("pop","acc");
1432                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1433                 if (!sz) break;
1434                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1435             }
1436             op->aop = aop;
1437             pic16_freeAsmop(op,NULL,ic,TRUE);
1438             if (_G.r0Pushed) {
1439                 pic16_emitcode("pop","ar0");
1440                 _G.r0Pushed--;
1441             }
1442
1443             if (_G.r1Pushed) {
1444                 pic16_emitcode("pop","ar1");
1445                 _G.r1Pushed--;
1446             }       
1447         }
1448 #endif
1449
1450     }
1451 #endif
1452
1453 dealloc:
1454     /* all other cases just dealloc */
1455     if (op ) {
1456         op->aop = NULL;
1457         if (IS_SYMOP(op)) {
1458             OP_SYMBOL(op)->aop = NULL;    
1459             /* if the symbol has a spill */
1460             if (SPIL_LOC(op))
1461                 SPIL_LOC(op)->aop = NULL;
1462         }
1463     }
1464 }
1465
1466 /*-----------------------------------------------------------------*/
1467 /* pic16_aopGet - for fetching value of the aop                          */
1468 /*-----------------------------------------------------------------*/
1469 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1470 {
1471     char *s = buffer ;
1472     char *rs;
1473
1474     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1475
1476     /* offset is greater than size then zero */
1477     if (offset > (aop->size - 1) &&
1478         aop->type != AOP_LIT)
1479         return zero;
1480
1481     /* depending on type */
1482     switch (aop->type) {
1483
1484     case AOP_FSR0:
1485     case AOP_FSR2:
1486       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1487       rs = Safe_calloc(1, strlen(s)+1);
1488       strcpy(rs, s);
1489       return (rs);
1490       
1491 #if 0
1492       /* if we need to increment it */
1493       while (offset > aop->coff)
1494         {
1495           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1496           aop->coff++;
1497         }
1498
1499       while (offset < aop->coff)
1500         {
1501           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1502           aop->coff--;
1503         }
1504       aop->coff = offset;
1505       if (aop->paged)
1506         {
1507           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1508           return (dname ? "acc" : "a");
1509         }
1510       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1511       rs = Safe_calloc (1, strlen (s) + 1);
1512       strcpy (rs, s);
1513       return rs;
1514 #endif
1515
1516         
1517     case AOP_IMMD:
1518         if (bit16) 
1519             sprintf (s,"%s",aop->aopu.aop_immd);
1520         else
1521             if (offset) 
1522                 sprintf(s,"(%s >> %d)",
1523                         aop->aopu.aop_immd,
1524                         offset*8);
1525             else
1526                 sprintf(s,"%s",
1527                         aop->aopu.aop_immd);
1528         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1529         rs = Safe_calloc(1,strlen(s)+1);
1530         strcpy(rs,s);   
1531         return rs;
1532         
1533     case AOP_DIR:
1534       if (offset) {
1535         sprintf(s,"(%s + %d)",
1536                 aop->aopu.aop_dir,
1537                 offset);
1538         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1539       } else
1540             sprintf(s,"%s",aop->aopu.aop_dir);
1541         rs = Safe_calloc(1,strlen(s)+1);
1542         strcpy(rs,s);   
1543         return rs;
1544         
1545     case AOP_REG:
1546       //if (dname) 
1547       //    return aop->aopu.aop_reg[offset]->dname;
1548       //else
1549             return aop->aopu.aop_reg[offset]->name;
1550         
1551     case AOP_CRY:
1552       //pic16_emitcode(";","%d",__LINE__);
1553       return aop->aopu.aop_dir;
1554         
1555     case AOP_ACC:
1556         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1557 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1558 //        assert( 0 );
1559 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1560         rs = Safe_strdup("WREG");
1561         return (rs);
1562
1563     case AOP_LIT:
1564         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1565         rs = Safe_calloc(1,strlen(s)+1);
1566         strcpy(rs,s);   
1567         return rs;
1568         
1569     case AOP_STR:
1570         aop->coff = offset ;
1571
1572 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1573 //          dname)
1574 //          return "acc";
1575         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1576           aop->type = AOP_ACC;
1577           return Safe_strdup("WREG");
1578         }
1579         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1580         
1581         return aop->aopu.aop_str[offset];
1582         
1583     case AOP_PCODE:
1584       {
1585         pCodeOp *pcop = aop->aopu.pcop;
1586         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1587         if(pcop->name) {
1588           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1589           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1590           if (offset) {
1591             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1592           } else {
1593             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1594           }
1595         } else
1596           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1597
1598       }
1599       rs = Safe_calloc(1,strlen(s)+1);
1600       strcpy(rs,s);   
1601       return rs;
1602
1603 #if 0
1604     case AOP_PAGED:
1605       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1606       if (offset) {
1607         sprintf(s,"(%s + %d)",
1608                 aop->aopu.aop_dir,
1609                 offset);
1610       } else
1611             sprintf(s,"%s",aop->aopu.aop_dir);
1612       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1613       rs = Safe_calloc(1,strlen(s)+1);
1614       strcpy(rs,s);   
1615       return rs;
1616 #endif
1617
1618     case AOP_STA:
1619         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1620         return (rs);
1621         
1622     case AOP_STK:
1623 //        pCodeOp *pcop = aop->aop
1624         break;
1625
1626     }
1627
1628     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1629     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1630            "aopget got unsupported aop->type");
1631     exit(0);
1632 }
1633
1634
1635
1636 /* lock has the following meaning: When allocating temporary registers
1637  * for stack variables storage, the value of the temporary register is
1638  * saved on stack. Its value is restored at the end. This procedure is
1639  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1640  * a possibility that before a call to pic16_aopOp, a temporary register
1641  * is allocated for a while and it is freed after some time, this will
1642  * mess the stack and values will not be restored properly. So use lock=1
1643  * to allocate temporary registers used internally by the programmer, and
1644  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1645  * to inform the compiler developer about a possible bug. This is an internal
1646  * feature for developing the compiler -- VR */
1647  
1648 int _TempReg_lock = 0;
1649 /*-----------------------------------------------------------------*/
1650 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1651 /*-----------------------------------------------------------------*/
1652 pCodeOp *pic16_popGetTempReg(int lock)
1653 {
1654   pCodeOp *pcop;
1655   symbol *cfunc;
1656
1657 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1658     if(_TempReg_lock) {
1659 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1660     }
1661     
1662     _TempReg_lock += lock;
1663     
1664     cfunc = currFunc;
1665     currFunc = NULL;
1666
1667     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1668     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1669       PCOR(pcop)->r->wasUsed=1;
1670       PCOR(pcop)->r->isFree=0;
1671
1672       /* push value on stack */
1673       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1674     }
1675
1676     currFunc = cfunc;
1677
1678   return pcop;
1679 }
1680
1681 /*-----------------------------------------------------------------*/
1682 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1683 /*                           is not part of f, but don't save if   */
1684 /*                           inside v                              */
1685 /*-----------------------------------------------------------------*/
1686 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1687 {
1688   pCodeOp *pcop=NULL;
1689   symbol *cfunc;
1690   int i;
1691
1692 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1693
1694     if(_TempReg_lock) {
1695 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1696     }
1697
1698     _TempReg_lock += lock;
1699
1700     cfunc = currFunc;
1701     currFunc = NULL;
1702
1703     i = bitVectFirstBit(f);
1704     while(i < 128) {
1705
1706       /* bypass registers that are used by function */
1707       if(!bitVectBitValue(f, i)) {
1708       
1709         /* bypass registers that are already allocated for stack access */
1710         if(!bitVectBitValue(v, i))  {
1711         
1712 //          debugf("getting register rIdx = %d\n", i);
1713           /* ok, get the operand */
1714           pcop = pic16_newpCodeOpReg( i );
1715     
1716           /* should never by NULL */
1717           assert( pcop != NULL );
1718
1719           
1720           /* sanity check */
1721           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1722             int found=0;
1723             
1724               PCOR(pcop)->r->wasUsed=1;
1725               PCOR(pcop)->r->isFree=0;
1726
1727
1728               {
1729                 regs *sr;
1730               
1731                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1732
1733                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1734                       /* already used in previous steps, break */
1735                       found=1;          
1736                       break;
1737                     }
1738                   }
1739               }
1740
1741               /* caller takes care of the following */
1742 //              bitVectSetBit(v, i);
1743
1744               if(!found) {
1745                 /* push value on stack */
1746                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1747                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1748               }
1749           
1750             break;
1751           }
1752         }
1753       }
1754       i++;
1755     }
1756
1757     currFunc = cfunc;
1758
1759   return pcop;
1760 }
1761
1762
1763 /*-----------------------------------------------------------------*/
1764 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1765 /*-----------------------------------------------------------------*/
1766 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1767 {
1768   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1769
1770   _TempReg_lock -= lock;
1771
1772   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1773     PCOR(pcop)->r->isFree = 1;
1774
1775     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1776   }
1777 }
1778 /*-----------------------------------------------------------------*/
1779 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1780 /*-----------------------------------------------------------------*/
1781 pCodeOp *pic16_popGetLabel(unsigned int key)
1782 {
1783
1784   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1785
1786   if(key>max_key)
1787     max_key = key;
1788
1789   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* pic16_popCopyReg - copy a pcode operator                              */
1794 /*-----------------------------------------------------------------*/
1795 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1796 {
1797   pCodeOpReg *pcor;
1798
1799   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1800   memcpy (pcor, pc, sizeof (pCodeOpReg));
1801   pcor->r->wasUsed = 1;
1802   
1803   //pcor->pcop.type = pc->pcop.type;
1804   if(pc->pcop.name) {
1805     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1806       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1807   } else
1808     pcor->pcop.name = NULL;
1809
1810   //pcor->r = pc->r;
1811   //pcor->rIdx = pc->rIdx;
1812   //pcor->r->wasUsed=1;
1813   //pcor->instance = pc->instance;
1814
1815 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1816
1817   return PCOP(pcor);
1818 }
1819
1820 /*-----------------------------------------------------------------*/
1821 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1822 /*-----------------------------------------------------------------*/
1823 pCodeOp *pic16_popGetLit(int lit)
1824 {
1825   return pic16_newpCodeOpLit(lit);
1826 }
1827
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1832 {
1833   return pic16_newpCodeOpLit2(lit, arg2);
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1841 {
1842   return pic16_newpCodeOpImmd(name, offset,index, 0);
1843 }
1844
1845
1846 /*-----------------------------------------------------------------*/
1847 /* pic16_popGet - asm operator to pcode operator conversion              */
1848 /*-----------------------------------------------------------------*/
1849 pCodeOp *pic16_popGetWithString(char *str)
1850 {
1851   pCodeOp *pcop;
1852
1853
1854   if(!str) {
1855     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1856     exit (1);
1857   }
1858
1859   pcop = pic16_newpCodeOp(str,PO_STR);
1860
1861   return pcop;
1862 }
1863
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popRegFromString -                                        */
1866 /*-----------------------------------------------------------------*/
1867 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1868 {
1869
1870   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1871   pcop->type = PO_DIR;
1872
1873   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1874   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1875
1876   if(!str)
1877     str = "BAD_STRING";
1878
1879   pcop->name = Safe_calloc(1,strlen(str)+1);
1880   strcpy(pcop->name,str);
1881
1882   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1883
1884   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1885
1886   /* make sure that register doesn't exist,
1887    * and operand isn't NULL
1888    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1889   if((PCOR(pcop)->r == NULL) 
1890     && (op)
1891     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1892 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1893 //              __FUNCTION__, __LINE__, str, size, offset);
1894
1895     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1896     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1897
1898   }
1899   PCOR(pcop)->instance = offset;
1900
1901   return pcop;
1902 }
1903
1904 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1905 {
1906   pCodeOp *pcop;
1907
1908 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1909
1910         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1911         PCOR(pcop)->rIdx = rIdx;
1912         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1913
1914         PCOR(pcop)->r->isFree = 0;
1915         PCOR(pcop)->r->wasUsed = 1;
1916
1917         pcop->type = PCOR(pcop)->r->pc_type;
1918
1919   return pcop;
1920 }
1921
1922 /*---------------------------------------------------------------------------------*/
1923 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1924 /*                 VR 030601                                                       */
1925 /*---------------------------------------------------------------------------------*/
1926 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1927 {
1928   pCodeOpReg2 *pcop2;
1929   pCodeOp *temp;
1930   
1931         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1932
1933         /* comment the following check, so errors to throw up */
1934 //      if(!pcop2)return NULL;
1935
1936         temp = pic16_popGet(aop_dst, offset);
1937         pcop2->pcop2 = temp;
1938         
1939   return PCOP(pcop2);
1940 }
1941
1942
1943
1944 /*--------------------------------------------------------------------------------.-*/
1945 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1946 /*                  VR 030601 , adapted by Hans Dorn                                */
1947 /*--------------------------------------------------------------------------------.-*/
1948 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1949 {
1950   pCodeOpReg2 *pcop2;
1951  
1952         pcop2 = (pCodeOpReg2 *)src;
1953         pcop2->pcop2 = dst;
1954         
1955         return PCOP(pcop2);
1956 }
1957
1958
1959
1960 /*---------------------------------------------------------------------------------*/
1961 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1962 /*                     movff instruction                                           */
1963 /*---------------------------------------------------------------------------------*/
1964 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1965 {
1966   pCodeOpReg2 *pcop2;
1967
1968         if(!noalloc) {
1969                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1970                 pcop2->pcop2 = pic16_popCopyReg(dst);
1971         } else {
1972                 /* the pCodeOp may be already allocated */
1973                 pcop2 = (pCodeOpReg2 *)(src);
1974                 pcop2->pcop2 = (pCodeOp *)(dst);
1975         }
1976
1977   return PCOP(pcop2);
1978 }
1979
1980
1981 /*-----------------------------------------------------------------*/
1982 /* pic16_popGet - asm operator to pcode operator conversion              */
1983 /*-----------------------------------------------------------------*/
1984 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1985 {
1986   //char *s = buffer ;
1987   char *rs;
1988   pCodeOp *pcop;
1989
1990     FENTRY2;
1991     /* offset is greater than
1992     size then zero */
1993
1994 //    if (offset > (aop->size - 1) &&
1995 //        aop->type != AOP_LIT)
1996 //      return NULL;  //zero;
1997
1998     /* depending on type */
1999     switch (aop->type) {
2000         
2001     case AOP_R0:
2002     case AOP_R1:
2003     case AOP_DPTR:
2004     case AOP_DPTR2:
2005         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2006         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2007         assert( 0 );
2008         return NULL;
2009
2010
2011     case AOP_FSR0:
2012     case AOP_FSR2:
2013       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2014       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2015       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2016       PCOR(pcop)->r->wasUsed = 1;
2017       PCOR(pcop)->r->isFree = 0;
2018       
2019       PCOR(pcop)->instance = offset;
2020       pcop->type = PCOR(pcop)->r->pc_type;
2021       return (pcop);
2022
2023     case AOP_IMMD:
2024       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2025       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2026
2027     case AOP_STA:
2028       /* pCodeOp is already allocated from aopForSym */
2029         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2030         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2031           
2032       return (pcop);
2033       
2034     case AOP_ACC:
2035       {
2036         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2037
2038         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2039
2040         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2041         
2042         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2043         PCOR(pcop)->rIdx = rIdx;
2044         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2045         PCOR(pcop)->r->wasUsed=1;
2046         PCOR(pcop)->r->isFree=0;
2047
2048         PCOR(pcop)->instance = offset;
2049         pcop->type = PCOR(pcop)->r->pc_type;
2050 //      rs = aop->aopu.aop_reg[offset]->name;
2051 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2052         return pcop;
2053
2054
2055 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2056 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2057
2058 //      assert( 0 );
2059       }
2060         
2061     case AOP_DIR:
2062       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2063       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2064         
2065 #if 0
2066     case AOP_PAGED:
2067       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2068       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2069 #endif
2070
2071     case AOP_REG:
2072       {
2073         int rIdx;
2074         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2075         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2076
2077         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2078         
2079         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2080 //      pcop->type = PO_GPR_REGISTER;
2081         PCOR(pcop)->rIdx = rIdx;
2082         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2083         PCOR(pcop)->r->wasUsed=1;
2084         PCOR(pcop)->r->isFree=0;
2085
2086         PCOR(pcop)->instance = offset;
2087         pcop->type = PCOR(pcop)->r->pc_type;
2088         
2089         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2090         rs = aop->aopu.aop_reg[offset]->name;
2091         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2092         return pcop;
2093       }
2094
2095     case AOP_CRY:
2096         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2097
2098       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2099       PCOR(pcop)->instance = offset;
2100       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2101       //if(PCOR(pcop)->r == NULL)
2102       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2103       return pcop;
2104         
2105     case AOP_LIT:
2106         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2107       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2108
2109     case AOP_STR:
2110       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2111       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2112
2113       /*
2114       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2115       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2116       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2117       pcop->type = PCOR(pcop)->r->pc_type;
2118       pcop->name = PCOR(pcop)->r->name;
2119
2120       return pcop;
2121       */
2122
2123     case AOP_PCODE:
2124       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2125                           __LINE__, 
2126                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2127       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2128       switch( aop->aopu.pcop->type ) {
2129         case PO_DIR: PCOR(pcop)->instance += offset; break;
2130         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2131         case PO_WREG:
2132             assert (offset==0);
2133             break;
2134         default:
2135           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2136           assert( 0 );  /* should never reach here */;
2137       }
2138       return pcop;
2139     }
2140
2141     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2142            "pic16_popGet got unsupported aop->type");
2143     exit(0);
2144 }
2145 /*-----------------------------------------------------------------*/
2146 /* pic16_aopPut - puts a string for a aop                                */
2147 /*-----------------------------------------------------------------*/
2148 void pic16_aopPut (asmop *aop, char *s, int offset)
2149 {
2150     char *d = buffer ;
2151     symbol *lbl ;
2152
2153     return;
2154
2155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2156
2157     if (aop->size && offset > ( aop->size - 1)) {
2158         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2159                "pic16_aopPut got offset > aop->size");
2160         exit(0);
2161     }
2162
2163     /* will assign value to value */
2164     /* depending on where it is ofcourse */
2165     switch (aop->type) {
2166     case AOP_DIR:
2167       if (offset) {
2168         sprintf(d,"(%s + %d)",
2169                 aop->aopu.aop_dir,offset);
2170         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2171
2172       } else
2173             sprintf(d,"%s",aop->aopu.aop_dir);
2174         
2175         if (strcmp(d,s)) {
2176           DEBUGpic16_emitcode(";","%d",__LINE__);
2177           if(strcmp(s,"W"))
2178             pic16_emitcode("movf","%s,w",s);
2179           pic16_emitcode("movwf","%s",d);
2180
2181           if(strcmp(s,"W")) {
2182             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2183             if(offset >= aop->size) {
2184               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2185               break;
2186             } else
2187               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2188           }
2189
2190           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2191
2192
2193         }
2194         break;
2195         
2196     case AOP_REG:
2197       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2198         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2199           /*
2200             if (*s == '@'           ||
2201                 strcmp(s,"r0") == 0 ||
2202                 strcmp(s,"r1") == 0 ||
2203                 strcmp(s,"r2") == 0 ||
2204                 strcmp(s,"r3") == 0 ||
2205                 strcmp(s,"r4") == 0 ||
2206                 strcmp(s,"r5") == 0 ||
2207                 strcmp(s,"r6") == 0 || 
2208                 strcmp(s,"r7") == 0 )
2209                 pic16_emitcode("mov","%s,%s  ; %d",
2210                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2211             else
2212           */
2213
2214           if(strcmp(s,"W")==0 )
2215             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2216
2217           pic16_emitcode("movwf","%s",
2218                    aop->aopu.aop_reg[offset]->name);
2219
2220           if(strcmp(s,zero)==0) {
2221             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2222
2223           } else if(strcmp(s,"W")==0) {
2224             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2225             pcop->type = PO_GPR_REGISTER;
2226
2227             PCOR(pcop)->rIdx = -1;
2228             PCOR(pcop)->r = NULL;
2229
2230             DEBUGpic16_emitcode(";","%d",__LINE__);
2231             pcop->name = Safe_strdup(s);
2232             pic16_emitpcode(POC_MOVFW,pcop);
2233             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2234           } else if(strcmp(s,one)==0) {
2235             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2236             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2237           } else {
2238             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2239           }
2240         }
2241         break;
2242         
2243     case AOP_DPTR:
2244     case AOP_DPTR2:
2245     
2246     if (aop->type == AOP_DPTR2)
2247     {
2248         genSetDPTR(1);
2249     }
2250     
2251         if (aop->code) {
2252             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2253                    "pic16_aopPut writting to code space");
2254             exit(0);
2255         }
2256         
2257         while (offset > aop->coff) {
2258             aop->coff++;
2259             pic16_emitcode ("inc","dptr");
2260         }
2261         
2262         while (offset < aop->coff) {
2263             aop->coff-- ;
2264             pic16_emitcode("lcall","__decdptr");
2265         }
2266         
2267         aop->coff = offset;
2268         
2269         /* if not in accumulater */
2270         MOVA(s);        
2271         
2272         pic16_emitcode ("movx","@dptr,a");
2273         
2274     if (aop->type == AOP_DPTR2)
2275     {
2276         genSetDPTR(0);
2277     }
2278         break;
2279         
2280     case AOP_R0:
2281     case AOP_R1:
2282         while (offset > aop->coff) {
2283             aop->coff++;
2284             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2285         }
2286         while (offset < aop->coff) {
2287             aop->coff-- ;
2288             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2289         }
2290         aop->coff = offset;
2291         
2292         if (aop->paged) {
2293             MOVA(s);           
2294             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2295             
2296         } else
2297             if (*s == '@') {
2298                 MOVA(s);
2299                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2300             } else
2301                 if (strcmp(s,"r0") == 0 ||
2302                     strcmp(s,"r1") == 0 ||
2303                     strcmp(s,"r2") == 0 ||
2304                     strcmp(s,"r3") == 0 ||
2305                     strcmp(s,"r4") == 0 ||
2306                     strcmp(s,"r5") == 0 ||
2307                     strcmp(s,"r6") == 0 || 
2308                     strcmp(s,"r7") == 0 ) {
2309                     char buffer[10];
2310                     sprintf(buffer,"a%s",s);
2311                     pic16_emitcode("mov","@%s,%s",
2312                              aop->aopu.aop_ptr->name,buffer);
2313                 } else
2314                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2315         
2316         break;
2317         
2318     case AOP_STK:
2319         if (strcmp(s,"a") == 0)
2320             pic16_emitcode("push","acc");
2321         else
2322             pic16_emitcode("push","%s",s);
2323         
2324         break;
2325         
2326     case AOP_CRY:
2327         /* if bit variable */
2328         if (!aop->aopu.aop_dir) {
2329             pic16_emitcode("clr","a");
2330             pic16_emitcode("rlc","a");
2331         } else {
2332             if (s == zero) 
2333                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2334             else
2335                 if (s == one)
2336                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2337                 else
2338                     if (!strcmp(s,"c"))
2339                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2340                     else {
2341                         lbl = newiTempLabel(NULL);
2342                         
2343                         if (strcmp(s,"a")) {
2344                             MOVA(s);
2345                         }
2346                         pic16_emitcode("clr","c");
2347                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2348                         pic16_emitcode("cpl","c");
2349                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2350                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2351                     }
2352         }
2353         break;
2354         
2355     case AOP_STR:
2356         aop->coff = offset;
2357         if (strcmp(aop->aopu.aop_str[offset],s))
2358             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2359         break;
2360         
2361     case AOP_ACC:
2362         aop->coff = offset;
2363         if (!offset && (strcmp(s,"acc") == 0))
2364             break;
2365         
2366         if (strcmp(aop->aopu.aop_str[offset],s))
2367             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2368         break;
2369
2370     default :
2371         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2372 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2373 //             "pic16_aopPut got unsupported aop->type");
2374 //      exit(0);    
2375     }    
2376
2377 }
2378
2379 /*-----------------------------------------------------------------*/
2380 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2381 /*-----------------------------------------------------------------*/
2382 void pic16_mov2w (asmop *aop, int offset)
2383 {
2384   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2385
2386   if(is_LitAOp(aop))
2387     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2388   else
2389     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2390 }
2391
2392 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2393 {
2394   if(is_LitAOp(src)) {
2395     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2396     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2397   } else {
2398     if(pic16_sameRegsOfs(src, dst, offset))return;
2399     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2400                       pic16_popGet(dst, offset)));
2401   }
2402 }
2403
2404 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2405 {
2406   if(is_LitAOp(src)) {
2407     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2408     pic16_emitpcode(POC_MOVWF, dst);
2409   } else {
2410     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2411   }
2412 }
2413
2414 void pic16_testStackOverflow(void)
2415 {
2416 #define GSTACK_TEST_NAME        "_gstack_test"
2417
2418   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2419   
2420   {
2421     symbol *sym;
2422
2423       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2424       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2425 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2426       checkAddSym(&externs, sym);
2427   }
2428
2429 }
2430
2431 /* push pcop into stack */
2432 void pic16_pushpCodeOp(pCodeOp *pcop)
2433 {
2434 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2435   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2436   if(pic16_options.gstack)
2437     pic16_testStackOverflow();
2438     
2439 }
2440
2441 /* pop pcop from stack */
2442 void pic16_poppCodeOp(pCodeOp *pcop)
2443 {
2444   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2445   if(pic16_options.gstack)
2446     pic16_testStackOverflow();
2447 }
2448
2449
2450 /*-----------------------------------------------------------------*/
2451 /* pushw - pushes wreg to stack                                    */
2452 /*-----------------------------------------------------------------*/
2453 void pushw(void)
2454 {
2455   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2456   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2457   if(pic16_options.gstack)
2458     pic16_testStackOverflow();
2459 }
2460
2461                 
2462 /*-----------------------------------------------------------------*/
2463 /* pushaop - pushes aop to stack                                   */
2464 /*-----------------------------------------------------------------*/
2465 void pushaop(asmop *aop, int offset)
2466 {
2467   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2468
2469   if(is_LitAOp(aop)) {
2470     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2471     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2472   } else {
2473     pic16_emitpcode(POC_MOVFF,
2474       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2475   }
2476
2477   if(pic16_options.gstack)
2478     pic16_testStackOverflow();
2479 }
2480
2481 /*-----------------------------------------------------------------*/
2482 /* popaop - pops aop from stack                                    */
2483 /*-----------------------------------------------------------------*/
2484 void popaop(asmop *aop, int offset)
2485 {
2486   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2487   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2488   if(pic16_options.gstack)
2489     pic16_testStackOverflow();
2490 }
2491
2492 void popaopidx(asmop *aop, int offset, int index)
2493 {
2494   int ofs=1;
2495
2496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2497
2498     if(STACK_MODEL_LARGE)ofs++;
2499
2500     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2501     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2502     if(pic16_options.gstack)
2503       pic16_testStackOverflow();
2504 }
2505
2506 #if !(USE_GENERIC_SIGNED_SHIFT)
2507 /*-----------------------------------------------------------------*/
2508 /* reAdjustPreg - points a register back to where it should        */
2509 /*-----------------------------------------------------------------*/
2510 static void reAdjustPreg (asmop *aop)
2511 {
2512     int size ;
2513
2514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2515     aop->coff = 0;
2516     if ((size = aop->size) <= 1)
2517         return ;
2518     size-- ;
2519     switch (aop->type) {
2520         case AOP_R0 :
2521         case AOP_R1 :
2522             while (size--)
2523                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2524             break;          
2525         case AOP_DPTR :
2526         case AOP_DPTR2:
2527             if (aop->type == AOP_DPTR2)
2528             {
2529                 genSetDPTR(1);
2530             } 
2531             while (size--)
2532             {
2533                 pic16_emitcode("lcall","__decdptr");
2534             }
2535                 
2536             if (aop->type == AOP_DPTR2)
2537             {
2538                 genSetDPTR(0);
2539             }                
2540             break;  
2541
2542     }   
2543
2544 }
2545 #endif
2546
2547 #if 0
2548 /*-----------------------------------------------------------------*/
2549 /* opIsGptr: returns non-zero if the passed operand is             */   
2550 /* a generic pointer type.                                         */
2551 /*-----------------------------------------------------------------*/ 
2552 static int opIsGptr(operand *op)
2553 {
2554     sym_link *type = operandType(op);
2555     
2556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2558     {
2559         return 1;
2560     }
2561     return 0;        
2562 }
2563 #endif
2564
2565 /*-----------------------------------------------------------------*/
2566 /* pic16_getDataSize - get the operand data size                         */
2567 /*-----------------------------------------------------------------*/
2568 int pic16_getDataSize(operand *op)
2569 {
2570     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2571
2572
2573     return AOP_SIZE(op);
2574
2575     // tsd- in the pic port, the genptr size is 1, so this code here
2576     // fails. ( in the 8051 port, the size was 4).
2577 #if 0
2578     int size;
2579     size = AOP_SIZE(op);
2580     if (size == GPTRSIZE)
2581     {
2582         sym_link *type = operandType(op);
2583         if (IS_GENPTR(type))
2584         {
2585             /* generic pointer; arithmetic operations
2586              * should ignore the high byte (pointer type).
2587              */
2588             size--;
2589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2590         }
2591     }
2592     return size;
2593 #endif
2594 }
2595
2596 /*-----------------------------------------------------------------*/
2597 /* pic16_outAcc - output Acc                                             */
2598 /*-----------------------------------------------------------------*/
2599 void pic16_outAcc(operand *result)
2600 {
2601   int size,offset;
2602   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2603   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2604
2605
2606   size = pic16_getDataSize(result);
2607   if(size){
2608     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2609     size--;
2610     offset = 1;
2611     /* unsigned or positive */
2612     while(size--)
2613       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2614   }
2615
2616 }
2617
2618 /*-----------------------------------------------------------------*/
2619 /* pic16_outBitC - output a bit C                                  */
2620 /*                 Move to result the value of Carry flag -- VR    */
2621 /*-----------------------------------------------------------------*/
2622 void pic16_outBitC(operand *result)
2623 {
2624   int i;
2625
2626     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2627
2628     /* if the result is bit */
2629     if (AOP_TYPE(result) == AOP_CRY) {
2630         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2631         pic16_aopPut(AOP(result),"c",0);
2632     } else {
2633
2634         i = AOP_SIZE(result);
2635         while(i--) {
2636                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2637         }
2638         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2639     }
2640 }
2641
2642 /*-----------------------------------------------------------------*/
2643 /* pic16_outBitOp - output a bit from Op                           */
2644 /*                 Move to result the value of set/clr op -- VR    */
2645 /*-----------------------------------------------------------------*/
2646 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2647 {
2648   int i;
2649
2650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2651
2652     /* if the result is bit */
2653     if (AOP_TYPE(result) == AOP_CRY) {
2654         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2655         pic16_aopPut(AOP(result),"c",0);
2656     } else {
2657
2658         i = AOP_SIZE(result);
2659         while(i--) {
2660                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2661         }
2662         pic16_emitpcode(POC_RRCF, pcop);          
2663         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2664     }
2665 }
2666
2667 /*-----------------------------------------------------------------*/
2668 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2669 /*-----------------------------------------------------------------*/
2670 void pic16_toBoolean(operand *oper)
2671 {
2672     int size = AOP_SIZE(oper) - 1;
2673     int offset = 1;
2674
2675     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2676
2677     if ( AOP_TYPE(oper) != AOP_ACC) {
2678       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2679     }
2680     while (size--) {
2681       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2682     }
2683 }
2684
2685 /*-----------------------------------------------------------------*/
2686 /* genUminusFloat - unary minus for floating points                */
2687 /*-----------------------------------------------------------------*/
2688 static void genUminusFloat(operand *op,operand *result)
2689 {
2690   int size ,offset =0 ;
2691   
2692     FENTRY;
2693     /* for this we just need to flip the 
2694     first it then copy the rest in place */
2695     size = AOP_SIZE(op);
2696     assert( size == AOP_SIZE(result) );
2697
2698     while(size--) {
2699       pic16_mov2f(AOP(result), AOP(op), offset);
2700       offset++;
2701     }
2702     
2703     /* toggle the MSB's highest bit */
2704     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2705 }
2706
2707 /*-----------------------------------------------------------------*/
2708 /* genUminus - unary minus code generation                         */
2709 /*-----------------------------------------------------------------*/
2710 static void genUminus (iCode *ic)
2711 {
2712   int size, i;
2713   sym_link *optype, *rtype;
2714   symbol *label;
2715   int needLabel=0;
2716
2717     FENTRY;     
2718     
2719     /* assign asmops */
2720     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2721     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2722
2723     /* if both in bit space then special case */
2724     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2725       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2726         
2727         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2728         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2729         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2730         goto release; 
2731     } 
2732
2733     optype = operandType(IC_LEFT(ic));
2734     rtype = operandType(IC_RESULT(ic));
2735
2736
2737     /* if float then do float stuff */
2738     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2739       if(IS_FIXED(optype))
2740         debugf("implement fixed16x16 type\n", 0);
2741         
2742         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2743         goto release;
2744     }
2745
2746     /* otherwise subtract from zero by taking the 2's complement */
2747     size = AOP_SIZE(IC_LEFT(ic));
2748     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2749     label = newiTempLabel ( NULL );
2750     
2751     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2752       for (i=size-1; i > 0; i--) {
2753         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2754       } // for
2755       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2756       for (i=1; i < size; i++) {
2757         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2758         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2759       } // for
2760     } else {
2761       for (i=size-1; i >= 0; i--) {
2762         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2763         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2764       } // for
2765       if (size > 1) {
2766         for (i=0; i < size-2; i++) {
2767           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2768           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2769         } // for
2770         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2771       } // if
2772       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2773     }
2774     if (needLabel)
2775       pic16_emitpLabel (label->key);
2776
2777 release:
2778     /* release the aops */
2779     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2780     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2781 }
2782
2783 #if 0
2784 /*-----------------------------------------------------------------*/
2785 /* saveRegisters - will look for a call and save the registers     */
2786 /*-----------------------------------------------------------------*/
2787 static void saveRegisters(iCode *lic) 
2788 {
2789     int i;
2790     iCode *ic;
2791     bitVect *rsave;
2792     sym_link *dtype;
2793
2794     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2795     /* look for call */
2796     for (ic = lic ; ic ; ic = ic->next) 
2797         if (ic->op == CALL || ic->op == PCALL)
2798             break;
2799
2800     if (!ic) {
2801         fprintf(stderr,"found parameter push with no function call\n");
2802         return ;
2803     }
2804
2805     /* if the registers have been saved already then
2806     do nothing */
2807     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2808         return ;
2809
2810     /* find the registers in use at this time 
2811     and push them away to safety */
2812     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2813                           ic->rUsed);
2814
2815     ic->regsSaved = 1;
2816     if (options.useXstack) {
2817         if (bitVectBitValue(rsave,R0_IDX))
2818             pic16_emitcode("mov","b,r0");
2819         pic16_emitcode("mov","r0,%s",spname);
2820         for (i = 0 ; i < pic16_nRegs ; i++) {
2821             if (bitVectBitValue(rsave,i)) {
2822                 if (i == R0_IDX)
2823                     pic16_emitcode("mov","a,b");
2824                 else
2825                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2826                 pic16_emitcode("movx","@r0,a");
2827                 pic16_emitcode("inc","r0");
2828             }
2829         }
2830         pic16_emitcode("mov","%s,r0",spname);
2831         if (bitVectBitValue(rsave,R0_IDX))
2832             pic16_emitcode("mov","r0,b");           
2833     }// else
2834     //for (i = 0 ; i < pic16_nRegs ; i++) {
2835     //    if (bitVectBitValue(rsave,i))
2836     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2837     //}
2838
2839     dtype = operandType(IC_LEFT(ic));
2840     if (currFunc && dtype && 
2841         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2842         IFFUNC_ISISR(currFunc->type) &&
2843         !ic->bankSaved) 
2844
2845         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2846
2847 }
2848 /*-----------------------------------------------------------------*/
2849 /* unsaveRegisters - pop the pushed registers                      */
2850 /*-----------------------------------------------------------------*/
2851 static void unsaveRegisters (iCode *ic)
2852 {
2853     int i;
2854     bitVect *rsave;
2855
2856     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2857     /* find the registers in use at this time 
2858     and push them away to safety */
2859     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2860                           ic->rUsed);
2861     
2862     if (options.useXstack) {
2863         pic16_emitcode("mov","r0,%s",spname);   
2864         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2865             if (bitVectBitValue(rsave,i)) {
2866                 pic16_emitcode("dec","r0");
2867                 pic16_emitcode("movx","a,@r0");
2868                 if (i == R0_IDX)
2869                     pic16_emitcode("mov","b,a");
2870                 else
2871                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2872             }       
2873
2874         }
2875         pic16_emitcode("mov","%s,r0",spname);
2876         if (bitVectBitValue(rsave,R0_IDX))
2877             pic16_emitcode("mov","r0,b");
2878     } //else
2879     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2880     //    if (bitVectBitValue(rsave,i))
2881     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2882     //}
2883
2884 }  
2885 #endif
2886
2887 #if 0  // patch 14
2888 /*-----------------------------------------------------------------*/
2889 /* pushSide -                                                      */
2890 /*-----------------------------------------------------------------*/
2891 static void pushSide(operand * oper, int size)
2892 {
2893         int offset = 0;
2894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2895         while (size--) {
2896                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2897                 if (AOP_TYPE(oper) != AOP_REG &&
2898                     AOP_TYPE(oper) != AOP_DIR &&
2899                     strcmp(l,"a") ) {
2900                         pic16_emitcode("mov","a,%s",l);
2901                         pic16_emitcode("push","acc");
2902                 } else
2903                         pic16_emitcode("push","%s",l);
2904         }
2905 }
2906 #endif // patch 14
2907
2908 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2909 {
2910   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2911     pic16_emitpcode(POC_MOVFW, src);
2912     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2913   } else {
2914     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2915         src, pic16_popGet(AOP(op), offset)));
2916   }
2917 }
2918
2919
2920 /*-----------------------------------------------------------------*/
2921 /* assignResultValue - assign results to oper, rescall==1 is       */
2922 /*                     called from genCall() or genPcall()         */
2923 /*-----------------------------------------------------------------*/
2924 static void assignResultValue(operand * oper, int rescall)
2925 {
2926   int size = AOP_SIZE(oper);
2927   int offset=0;
2928   
2929     FENTRY2;
2930 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2931     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2932
2933     if(rescall) {
2934       /* assign result from a call/pcall function() */
2935                 
2936       /* function results are stored in a special order,
2937        * see top of file with Function return policy, or manual */
2938
2939       if(size <= 4) {
2940         /* 8-bits, result in WREG */
2941         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2942                         
2943         if(size>1) {
2944           /* 16-bits, result in PRODL:WREG */
2945           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2946         }
2947                         
2948         if(size>2) {
2949           /* 24-bits, result in PRODH:PRODL:WREG */
2950           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2951         }
2952                         
2953         if(size>3) {
2954           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2955           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2956         }
2957       
2958       } else {
2959         /* >32-bits, result on stack, and FSR0 points to beginning.
2960          * Fix stack when done */
2961         /* FIXME FIXME */
2962 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2963         while (size--) {
2964 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2965 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2966                 
2967           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2968           GpsuedoStkPtr++;
2969         }
2970                         
2971         /* fix stack */
2972         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2973         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2974         if(STACK_MODEL_LARGE) {
2975           emitSKPNC;
2976           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2977         }
2978       }                 
2979     } else {
2980       int areg = 0;             /* matching argument register */
2981       
2982 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2983       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2984
2985
2986       /* its called from genReceive (probably) -- VR */
2987       /* I hope this code will not be called from somewhere else in the future! 
2988        * We manually set the pseudo stack pointer in genReceive. - dw
2989        */
2990       if(!GpsuedoStkPtr && _G.useWreg) {
2991 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2992
2993         /* The last byte in the assignment is in W */
2994         if(areg <= GpsuedoStkPtr) {
2995           size--;
2996           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2997           offset++;
2998 //          debugf("receive from WREG\n", 0);
2999         }
3000         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3001       }
3002 //      GpsuedoStkPtr++;
3003       _G.stack_lat = AOP_SIZE(oper)-1;
3004
3005       while (size) {
3006         size--;
3007         GpsuedoStkPtr++;
3008         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3009 //        debugf("receive from STACK\n", 0);
3010         offset++;
3011       }
3012     }
3013 }
3014
3015
3016 /*-----------------------------------------------------------------*/
3017 /* genIpush - generate code for pushing this gets a little complex */
3018 /*-----------------------------------------------------------------*/
3019 static void genIpush (iCode *ic)
3020 {
3021 //  int size, offset=0;
3022
3023   FENTRY;
3024   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3025
3026   if(ic->parmPush) {
3027     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3028
3029     /* send to stack as normal */
3030     addSet(&_G.sendSet,ic);
3031 //    addSetHead(&_G.sendSet,ic);
3032     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3033   }
3034
3035         
3036 #if 0
3037     int size, offset = 0 ;
3038     char *l;
3039
3040
3041     /* if this is not a parm push : ie. it is spill push 
3042     and spill push is always done on the local stack */
3043     if (!ic->parmPush) {
3044
3045         /* and the item is spilt then do nothing */
3046         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3047             return ;
3048
3049         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3050         size = AOP_SIZE(IC_LEFT(ic));
3051         /* push it on the stack */
3052         while(size--) {
3053             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3054             if (*l == '#') {
3055                 MOVA(l);
3056                 l = "acc";
3057             }
3058             pic16_emitcode("push","%s",l);
3059         }
3060         return ;        
3061     }
3062
3063     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3064 #endif
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genIpop - recover the registers: can happen only for spilling   */
3069 /*-----------------------------------------------------------------*/
3070 static void genIpop (iCode *ic)
3071 {
3072   FENTRY;
3073   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3074 #if 0
3075     int size,offset ;
3076
3077
3078     /* if the temp was not pushed then */
3079     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3080         return ;
3081
3082     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3083     size = AOP_SIZE(IC_LEFT(ic));
3084     offset = (size-1);
3085     while (size--) 
3086         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3087                                    FALSE,TRUE));
3088
3089     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3090 #endif
3091 }
3092
3093 #if 0
3094 /*-----------------------------------------------------------------*/
3095 /* unsaverbank - restores the resgister bank from stack            */
3096 /*-----------------------------------------------------------------*/
3097 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3098 {
3099   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3100 #if 0
3101     int i;
3102     asmop *aop ;
3103     regs *r = NULL;
3104
3105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3106     if (popPsw) {
3107         if (options.useXstack) {
3108             aop = newAsmop(0);
3109             r = getFreePtr(ic,&aop,FALSE);
3110             
3111             
3112             pic16_emitcode("mov","%s,_spx",r->name);
3113             pic16_emitcode("movx","a,@%s",r->name);
3114             pic16_emitcode("mov","psw,a");
3115             pic16_emitcode("dec","%s",r->name);
3116             
3117         }else
3118             pic16_emitcode ("pop","psw");
3119     }
3120
3121     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3122         if (options.useXstack) {       
3123             pic16_emitcode("movx","a,@%s",r->name);
3124             //pic16_emitcode("mov","(%s+%d),a",
3125             //       regspic16[i].base,8*bank+regspic16[i].offset);
3126             pic16_emitcode("dec","%s",r->name);
3127
3128         } else 
3129           pic16_emitcode("pop",""); //"(%s+%d)",
3130         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3131     }
3132
3133     if (options.useXstack) {
3134
3135         pic16_emitcode("mov","_spx,%s",r->name);
3136         pic16_freeAsmop(NULL,aop,ic,TRUE);
3137
3138     }
3139 #endif 
3140 }
3141
3142 /*-----------------------------------------------------------------*/
3143 /* saverbank - saves an entire register bank on the stack          */
3144 /*-----------------------------------------------------------------*/
3145 static void saverbank (int bank, iCode *ic, bool pushPsw)
3146 {
3147   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3148 #if 0
3149     int i;
3150     asmop *aop ;
3151     regs *r = NULL;
3152
3153     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3154     if (options.useXstack) {
3155
3156         aop = newAsmop(0);
3157         r = getFreePtr(ic,&aop,FALSE);  
3158         pic16_emitcode("mov","%s,_spx",r->name);
3159
3160     }
3161
3162     for (i = 0 ; i < pic16_nRegs ;i++) {
3163         if (options.useXstack) {
3164             pic16_emitcode("inc","%s",r->name);
3165             //pic16_emitcode("mov","a,(%s+%d)",
3166             //         regspic16[i].base,8*bank+regspic16[i].offset);
3167             pic16_emitcode("movx","@%s,a",r->name);           
3168         } else 
3169           pic16_emitcode("push","");// "(%s+%d)",
3170                      //regspic16[i].base,8*bank+regspic16[i].offset);
3171     }
3172     
3173     if (pushPsw) {
3174         if (options.useXstack) {
3175             pic16_emitcode("mov","a,psw");
3176             pic16_emitcode("movx","@%s,a",r->name);     
3177             pic16_emitcode("inc","%s",r->name);
3178             pic16_emitcode("mov","_spx,%s",r->name);       
3179             pic16_freeAsmop (NULL,aop,ic,TRUE);
3180             
3181         } else
3182             pic16_emitcode("push","psw");
3183         
3184         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3185     }
3186     ic->bankSaved = 1;
3187 #endif
3188 }
3189 #endif  /* 0 */
3190
3191
3192 static int wparamCmp(void *p1, void *p2)
3193 {
3194   return (!strcmp((char *)p1, (char *)p2));
3195 }
3196
3197 int inWparamList(char *s)
3198 {
3199   return isinSetWith(wparamList, s, wparamCmp);
3200
3201
3202
3203 /*-----------------------------------------------------------------*/
3204 /* genCall - generates a call statement                            */
3205 /*-----------------------------------------------------------------*/
3206 static void genCall (iCode *ic)
3207 {
3208   sym_link *ftype;   
3209   int stackParms=0;
3210   int use_wreg=0;
3211   int inwparam=0;
3212   char *fname;
3213   
3214     FENTRY;
3215
3216     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3217     /* if caller saves & we have not saved then */
3218 //    if (!ic->regsSaved)
3219 //      saveRegisters(ic);
3220
3221         /* initialise stackParms for IPUSH pushes */
3222 //      stackParms = psuedoStkPtr;
3223 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3224     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3225     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3226
3227 #if 0
3228     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3229 #endif
3230
3231     /* if send set is not empty the assign */
3232     if (_G.sendSet) {
3233       iCode *sic;
3234       int psuedoStkPtr=-1; 
3235       int firstTimeThruLoop = 1;
3236
3237
3238         /* reverse sendSet if function is not reentrant */
3239         if(!IFFUNC_ISREENT(ftype))
3240           _G.sendSet = reverseSet(_G.sendSet);
3241
3242         /* First figure how many parameters are getting passed */
3243         stackParms = 0;
3244         use_wreg = 0;
3245         
3246         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3247           int size;
3248 //          int offset = 0;
3249
3250             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3251             size = AOP_SIZE(IC_LEFT(sic));
3252
3253             stackParms += size;
3254
3255             /* pass the last byte through WREG */
3256             if(inwparam) {
3257
3258               while (size--) {
3259                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3260                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3261                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3262
3263                 if(!firstTimeThruLoop) {
3264                   /* If this is not the first time we've been through the loop
3265                    * then we need to save the parameter in a temporary
3266                    * register. The last byte of the last parameter is
3267                    * passed in W. */
3268
3269                   pushw();
3270 //                  --psuedoStkPtr;             // sanity check
3271                   use_wreg = 1;
3272                 }
3273                 
3274                 firstTimeThruLoop=0;
3275
3276                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3277
3278 //                offset++;
3279               }
3280             } else {
3281               /* all arguments are passed via stack */
3282               use_wreg = 0;
3283
3284               while (size--) {
3285                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3286                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3287                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3288
3289 //                pushaop(AOP(IC_LEFT(sic)), size);
3290                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3291
3292                 if(!_G.resDirect)
3293                   pushw();
3294               }
3295             }
3296
3297             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3298           }
3299
3300           if(inwparam) {
3301             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3302               pushw();  /* save last parameter to stack if functions has varargs */
3303               use_wreg = 0;
3304             } else
3305               use_wreg = 1;
3306           } else use_wreg = 0;
3307
3308           _G.stackRegSet = _G.sendSet;
3309           _G.sendSet = NULL;
3310     }
3311
3312     /* make the call */
3313     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3314
3315     GpsuedoStkPtr=0;
3316     
3317     /* if we need to assign a result value */
3318     if ((IS_ITEMP(IC_RESULT(ic))
3319           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3320               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3321         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3322
3323       _G.accInUse++;
3324       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3325       _G.accInUse--;
3326
3327       assignResultValue(IC_RESULT(ic), 1);
3328
3329       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3330                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3331                 
3332       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3333     }
3334
3335     if(!stackParms && ic->parmBytes) {
3336       stackParms = ic->parmBytes;
3337     }
3338       
3339     stackParms -= use_wreg;
3340     
3341     if(stackParms>0) {
3342       if(stackParms == 1) {
3343         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3344       } else {
3345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3346         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3347       }
3348       if(STACK_MODEL_LARGE) {
3349         emitSKPNC;
3350         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3351       }
3352     }
3353
3354 #if 0
3355     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3356 #endif
3357
3358     /* adjust the stack for parameters if required */
3359 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3360
3361 #if 0
3362       /* if register bank was saved then pop them */
3363       if (ic->bankSaved)
3364         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3365
3366       /* if we hade saved some registers then unsave them */
3367       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3368         unsaveRegisters (ic);
3369 #endif
3370 }
3371
3372
3373
3374 /*-----------------------------------------------------------------*/
3375 /* genPcall - generates a call by pointer statement                */
3376 /*            new version, created from genCall - HJD              */
3377 /*-----------------------------------------------------------------*/
3378 static void genPcall (iCode *ic)
3379 {
3380   sym_link *ftype, *fntype;
3381   int stackParms=0;
3382   symbol *retlbl = newiTempLabel(NULL);
3383   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3384   
3385     FENTRY;
3386
3387     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3388     fntype = operandType( IC_LEFT(ic) )->next;
3389
3390     /* if send set is not empty the assign */
3391     if (_G.sendSet) {
3392       iCode *sic;
3393       int psuedoStkPtr=-1; 
3394
3395       /* reverse sendSet if function is not reentrant */
3396       if(!IFFUNC_ISREENT(fntype))
3397         _G.sendSet = reverseSet(_G.sendSet);
3398
3399       stackParms = 0;
3400       
3401       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3402         int size;
3403
3404           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3405           size = AOP_SIZE(IC_LEFT(sic));
3406           stackParms += size;
3407
3408           /* all parameters are passed via stack, since WREG is clobbered
3409            * by the calling sequence */
3410           while (size--) {
3411             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3413             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3414
3415             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3416             pushw();
3417           }
3418
3419           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3420       }
3421
3422       _G.stackRegSet = _G.sendSet;
3423       _G.sendSet = NULL;
3424     }
3425
3426     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3427
3428     // push return address
3429     // push $ on return stack, then replace with retlbl
3430
3431     /* Thanks to Thorsten Klose for pointing out that the following
3432      * snippet should be interrupt safe */
3433     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3434     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3435
3436     pic16_emitpcodeNULLop(POC_PUSH);
3437
3438     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3439     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3440     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3441     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3442     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3443     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3444
3445
3446     /* restore interrupt control register */
3447     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3448     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3449
3450     /* make the call by writing the pointer into pc */
3451     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3452     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3453
3454     // note: MOVFF to PCL not allowed
3455     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3456     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3457
3458
3459     /* return address is here: (X) */
3460     pic16_emitpLabelFORCE(retlbl->key);
3461
3462     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3463
3464     GpsuedoStkPtr=0;
3465     /* if we need assign a result value */
3466     if ((IS_ITEMP(IC_RESULT(ic))
3467           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3468               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3469         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3470
3471       _G.accInUse++;
3472       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3473       _G.accInUse--;
3474
3475       assignResultValue(IC_RESULT(ic), 1);
3476
3477       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3478               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3479                 
3480       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3481     }
3482
3483 //    stackParms -= use_wreg;
3484     
3485     if(stackParms>0) {
3486       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3487       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3488       if(STACK_MODEL_LARGE) {
3489         emitSKPNC;
3490         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3491       }
3492     }
3493 }
3494
3495 /*-----------------------------------------------------------------*/
3496 /* resultRemat - result  is rematerializable                       */
3497 /*-----------------------------------------------------------------*/
3498 static int resultRemat (iCode *ic)
3499 {
3500   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3501   if (SKIP_IC(ic) || ic->op == IFX)
3502     return 0;
3503
3504   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3505     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3506     if (sym->remat && !POINTER_SET(ic)) 
3507       return 1;
3508   }
3509
3510   return 0;
3511 }
3512
3513 #if defined(__BORLANDC__) || defined(_MSC_VER)
3514 #define STRCASECMP stricmp
3515 #else
3516 #define STRCASECMP strcasecmp
3517 #endif
3518
3519 #if 0
3520 /*-----------------------------------------------------------------*/
3521 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3522 /*-----------------------------------------------------------------*/
3523 static bool inExcludeList(char *s)
3524 {
3525   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3526     int i =0;
3527     
3528     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3529     if (options.excludeRegs[i] &&
3530     STRCASECMP(options.excludeRegs[i],"none") == 0)
3531         return FALSE ;
3532
3533     for ( i = 0 ; options.excludeRegs[i]; i++) {
3534         if (options.excludeRegs[i] &&
3535         STRCASECMP(s,options.excludeRegs[i]) == 0)
3536             return TRUE;
3537     }
3538     return FALSE ;
3539 }
3540 #endif
3541
3542 /*-----------------------------------------------------------------*/
3543 /* genFunction - generated code for function entry                 */
3544 /*-----------------------------------------------------------------*/
3545 static void genFunction (iCode *ic)
3546 {
3547   symbol *sym;
3548   sym_link *ftype;
3549   
3550     FENTRY;
3551     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3552
3553     pic16_labelOffset += (max_key+4);
3554     max_key=0;
3555     GpsuedoStkPtr=0;
3556     _G.nRegsSaved = 0;
3557         
3558     ftype = operandType(IC_LEFT(ic));
3559     sym = OP_SYMBOL(IC_LEFT(ic));
3560
3561     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3562       /* create an absolute section at the interrupt vector:
3563        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3564       symbol *asym;
3565       char asymname[128];
3566       pBlock *apb;
3567
3568 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3569
3570         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3571           sprintf(asymname, "ivec_%s", sym->name);
3572         else
3573           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3574   
3575         /* when an interrupt is declared as naked, do not emit the special
3576          * wrapper segment at vector address. The user should take care for
3577          * this instead. -- VR */
3578
3579         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3580           asym = newSymbol(asymname, 0);
3581           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3582           pic16_addpBlock( apb );
3583
3584           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3585           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3586           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3587           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3588           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3589                 
3590           /* mark the end of this tiny function */
3591           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3592         } else {
3593           sprintf(asymname, "%s", sym->rname);
3594         }
3595
3596         {
3597           absSym *abSym;
3598
3599             abSym = Safe_calloc(1, sizeof(absSym));
3600             strcpy(abSym->name, asymname);
3601
3602             switch( FUNC_INTNO(sym->type) ) {
3603               case 0: abSym->address = 0x000000; break;
3604               case 1: abSym->address = 0x000008; break;
3605               case 2: abSym->address = 0x000018; break;
3606               
3607               default:
3608 //                fprintf(stderr, "no interrupt number is given\n");
3609                 abSym->address = -1; break;
3610             }
3611
3612             /* relocate interrupt vectors if needed */
3613             if(abSym->address != -1)
3614               abSym->address += pic16_options.ivt_loc;
3615
3616             addSet(&absSymSet, abSym);
3617         }
3618     }
3619
3620     /* create the function header */
3621     pic16_emitcode(";","-----------------------------------------");
3622     pic16_emitcode(";"," function %s",sym->name);
3623     pic16_emitcode(";","-----------------------------------------");
3624
3625     pic16_emitcode("","%s:",sym->rname);
3626     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3627
3628     {
3629       absSym *ab;
3630
3631         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3632           if(!strcmp(ab->name, sym->rname)) {
3633             pic16_pBlockConvert2Absolute(pb);
3634             break;
3635           }
3636         }
3637     }
3638
3639     if(IFFUNC_ISNAKED(ftype)) {
3640       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3641       return;
3642     }
3643         
3644     /* if critical function then turn interrupts off */
3645     if (IFFUNC_ISCRITICAL(ftype)) {
3646       //pic16_emitcode("clr","ea");
3647     }
3648
3649     currFunc = sym;             /* update the currFunc symbol */
3650     _G.fregsUsed = sym->regsUsed;
3651     _G.sregsAlloc = newBitVect(128);
3652     
3653
3654     /* if this is an interrupt service routine then
3655      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3656     if (IFFUNC_ISISR(sym->type)) {
3657         _G.usefastretfie = 1;   /* use shadow registers by default */
3658         
3659         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3660         if(!FUNC_ISSHADOWREGS(sym->type)) {
3661           /* do not save WREG,STATUS,BSR for high priority interrupts
3662            * because they are stored in the hardware shadow registers already */
3663           _G.usefastretfie = 0;
3664           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3665           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3666           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3667         }
3668
3669         /* these should really be optimized somehow, because not all
3670          * interrupt handlers modify them */
3671         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3672         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3673         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3674         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3675         
3676 //        pic16_pBlockConvert2ISR(pb);
3677     }
3678
3679     /* emit code to setup stack frame if user enabled,
3680      * and function is not main() */
3681     
3682 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3683     if(strcmp(sym->name, "main")) {
3684       if(0 
3685         || !options.ommitFramePtr 
3686 //        || sym->regsUsed
3687         || IFFUNC_ARGS(sym->type)
3688         || FUNC_HASSTACKPARM(sym->etype)
3689         ) {
3690         /* setup the stack frame */
3691         if(STACK_MODEL_LARGE)
3692           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3693         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3694
3695         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3696         if(STACK_MODEL_LARGE)
3697           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3698       }
3699     }
3700
3701     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3702           && sym->stack) {
3703
3704       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3705
3706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3707       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3708       emitSKPC;
3709       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3710     }
3711           
3712     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3713       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3714         _G.useWreg = 0;
3715       else
3716         _G.useWreg = 1;
3717     } else
3718       _G.useWreg = 0;
3719
3720     /* if callee-save to be used for this function
3721      * then save the registers being used in this function */
3722 //    if (IFFUNC_CALLEESAVES(sym->type))
3723     {
3724       int i;
3725
3726         /* if any registers used */
3727         if (sym->regsUsed) {
3728           /* save the registers used */
3729           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3730           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3731           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3732             if (bitVectBitValue(sym->regsUsed,i)) {
3733               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3734               _G.nRegsSaved++;
3735
3736               if(!pic16_regWithIdx(i)->wasUsed) {
3737                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3738                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3739                 pic16_regWithIdx(i)->wasUsed = 1;
3740               }
3741             }
3742           }
3743           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3744         }
3745     }
3746         
3747     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3748 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3749 }
3750
3751 /*-----------------------------------------------------------------*/
3752 /* genEndFunction - generates epilogue for functions               */
3753 /*-----------------------------------------------------------------*/
3754 static void genEndFunction (iCode *ic)
3755 {
3756   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3757
3758     FENTRY;
3759
3760     if(IFFUNC_ISNAKED(sym->type)) {
3761       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3762       return;
3763     }
3764
3765     _G.stack_lat = 0;
3766
3767     /* add code for ISCRITICAL */
3768     if(IFFUNC_ISCRITICAL(sym->type)) {
3769       /* if critical function, turn on interrupts */
3770       
3771       /* TODO: add code here -- VR */
3772     }
3773     
3774 //    sym->regsUsed = _G.fregsUsed;
3775     
3776     /* now we need to restore the registers */
3777     /* if any registers used */
3778
3779     /* first restore registers that might be used for stack access */
3780     if(_G.sregsAllocSet) {
3781     regs *sr;
3782     
3783       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3784       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3785         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3786       }
3787     }
3788
3789     if (sym->regsUsed) {
3790       int i;
3791
3792         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3793         /* restore registers used */
3794         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3795         for ( i = sym->regsUsed->size; i >= 0; i--) {
3796           if (bitVectBitValue(sym->regsUsed,i)) {
3797             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3798             _G.nRegsSaved--;
3799           }
3800         }
3801         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3802     }
3803
3804       
3805
3806     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3807           && sym->stack) {
3808       if (sym->stack == 1) {
3809         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3810         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3811       } else {
3812         // we have to add more than one...
3813         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3814         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3815         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3816         emitSKPNC;
3817         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3818         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3819         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3820       }
3821     }
3822
3823     if(strcmp(sym->name, "main")) {
3824       if(0
3825         || !options.ommitFramePtr
3826 //        || sym->regsUsed
3827         || IFFUNC_ARGS(sym->type)
3828         || FUNC_HASSTACKPARM(sym->etype)
3829         ) {
3830         /* restore stack frame */
3831         if(STACK_MODEL_LARGE)
3832           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3833         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3834       }
3835     }
3836
3837     _G.useWreg = 0;
3838
3839     if (IFFUNC_ISISR(sym->type)) {
3840       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3841       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3842       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3843       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3844
3845       if(!FUNC_ISSHADOWREGS(sym->type)) {
3846         /* do not restore interrupt vector for WREG,STATUS,BSR
3847          * for high priority interrupt, see genFunction */
3848         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3849         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3850         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3851       }
3852 //      _G.interruptvector = 0;         /* sanity check */
3853
3854
3855       /* if debug then send end of function */
3856 /*      if (options.debug && currFunc)  */
3857       if (currFunc) {
3858         debugFile->writeEndFunction (currFunc, ic, 1);
3859       }
3860         
3861       if(_G.usefastretfie)
3862         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3863       else
3864         pic16_emitpcodeNULLop(POC_RETFIE);
3865
3866       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3867       
3868       _G.usefastretfie = 0;
3869       return;
3870     }
3871
3872     if (IFFUNC_ISCRITICAL(sym->type)) {
3873       pic16_emitcode("setb","ea");
3874     }
3875
3876     /* if debug then send end of function */
3877     if (currFunc) {
3878       debugFile->writeEndFunction (currFunc, ic, 1);
3879     }
3880
3881     /* insert code to restore stack frame, if user enabled it
3882      * and function is not main() */
3883          
3884
3885     pic16_emitpcodeNULLop(POC_RETURN);
3886
3887     /* Mark the end of a function */
3888     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3889 }
3890
3891
3892 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3893 {
3894   unsigned long lit=1;
3895   operand *op;
3896
3897     op = IC_LEFT(ic);
3898   
3899     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3900     if(AOP_TYPE(op) == AOP_LIT) {
3901       if(!IS_FLOAT(operandType( op ))) {
3902         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3903       } else {
3904         union {
3905           unsigned long lit_int;
3906           float lit_float;
3907         } info;
3908         
3909         /* take care if literal is a float */
3910         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3911         lit = info.lit_int;
3912       }
3913     }
3914
3915     if(is_LitOp(op)) {
3916       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3917         pic16_emitpcode(POC_CLRF, dest);
3918       } else {
3919         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3920         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3921       }
3922     } else {
3923       if(dest->type == PO_WREG && (offset == 0)) {
3924         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3925       return;
3926     }
3927     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3928   }
3929 }
3930
3931 /*-----------------------------------------------------------------*/
3932 /* genRet - generate code for return statement                     */
3933 /*-----------------------------------------------------------------*/
3934 static void genRet (iCode *ic)
3935 {
3936   int size;
3937   operand *left;
3938
3939     FENTRY;
3940         /* if we have no return value then
3941          * just generate the "ret" */
3942         
3943         if (!IC_LEFT(ic)) 
3944                 goto jumpret;       
3945     
3946         /* we have something to return then
3947          * move the return value into place */
3948         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3949         size = AOP_SIZE(IC_LEFT(ic));
3950
3951         if(size <= 4) {
3952           if(size>3)
3953             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3954           
3955           if(size>2)
3956             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3957
3958           if(size>1)
3959             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3960           
3961           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3962
3963         } else {
3964                 /* >32-bits, setup stack and FSR0 */
3965                 while (size--) {
3966 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3967 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3968
3969                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3970
3971 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3972                         GpsuedoStkPtr++;
3973                 }
3974                         
3975                 /* setup FSR0 */
3976                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3978
3979                 if(STACK_MODEL_LARGE) {
3980                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3981                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3982                 } else {
3983                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3984                 }
3985         }
3986                                 
3987 #if 0
3988         /* old code, left here for reference -- VR */    
3989         while (size--) {
3990           char *l ;
3991
3992                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3993                         /* #NOCHANGE */
3994                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3995                         pic16_emitpcomment("push %s",l);
3996                         pushed++;
3997                 } else {
3998                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3999                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4000                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4001                         
4002                         if (strcmp(fReturn[offset],l)) {
4003                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4004                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4005                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4006                                 } else {
4007                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4008                                 }
4009                                 
4010                                 if(size) {
4011                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4012                                 }
4013                                 offset++;
4014                         }
4015                 }
4016         }    
4017
4018         if (pushed) {
4019                 while(pushed) {
4020                         pushed--;
4021                         if (strcmp(fReturn[pushed],"a"))
4022                                 pic16_emitcode("pop",fReturn[pushed]);
4023                         else
4024                                 pic16_emitcode("pop","acc");
4025                 }
4026         }
4027 #endif
4028
4029
4030         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4031     
4032 jumpret:
4033         /* generate a jump to the return label
4034          * if the next is not the return statement */
4035         if (!(ic->next && ic->next->op == LABEL
4036                 && IC_LABEL(ic->next) == returnLabel)) {
4037         
4038                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4039                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4040         }
4041 }
4042
4043 /*-----------------------------------------------------------------*/
4044 /* genLabel - generates a label                                    */
4045 /*-----------------------------------------------------------------*/
4046 static void genLabel (iCode *ic)
4047 {
4048   FENTRY;
4049
4050   /* special case never generate */
4051   if (IC_LABEL(ic) == entryLabel)
4052     return ;
4053
4054   pic16_emitpLabel(IC_LABEL(ic)->key);
4055 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4056 }
4057
4058 /*-----------------------------------------------------------------*/
4059 /* genGoto - generates a goto                                      */
4060 /*-----------------------------------------------------------------*/
4061 //tsd
4062 static void genGoto (iCode *ic)
4063 {
4064   FENTRY;
4065   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4066 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4067 }
4068
4069
4070 /*-----------------------------------------------------------------*/
4071 /* genMultbits :- multiplication of bits                           */
4072 /*-----------------------------------------------------------------*/
4073 static void genMultbits (operand *left, 
4074                          operand *right, 
4075                          operand *result)
4076 {
4077   FENTRY;
4078
4079   if(!pic16_sameRegs(AOP(result),AOP(right)))
4080     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4081
4082   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4083   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4084   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4085
4086 }
4087
4088
4089 /*-----------------------------------------------------------------*/
4090 /* genMultOneByte : 8 bit multiplication & division                */
4091 /*-----------------------------------------------------------------*/
4092 static void genMultOneByte (operand *left,
4093                             operand *right,
4094                             operand *result)
4095 {
4096
4097   FENTRY;
4098   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4099   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4100
4101   /* (if two literals, the value is computed before) */
4102   /* if one literal, literal on the right */
4103   if (AOP_TYPE(left) == AOP_LIT){
4104     operand *t = right;
4105     right = left;
4106     left = t;
4107   }
4108
4109         /* size is already checked in genMult == 1 */
4110 //      size = AOP_SIZE(result);
4111
4112         if (AOP_TYPE(right) == AOP_LIT){
4113                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4114                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4115                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4116                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4117         } else {
4118                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4119                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4120                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4121                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4122         }
4123         
4124         pic16_genMult8X8_8 (left, right,result);
4125 }
4126
4127 /*-----------------------------------------------------------------*/
4128 /* genMultOneWord : 16 bit multiplication                          */
4129 /*-----------------------------------------------------------------*/
4130 static void genMultOneWord (operand *left,
4131                             operand *right,
4132                             operand *result)
4133 {
4134   FENTRY;
4135   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4136   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4137
4138   /* (if two literals, the value is computed before)
4139    * if one literal, literal on the right */
4140   if (AOP_TYPE(left) == AOP_LIT){
4141     operand *t = right;
4142     right = left;
4143     left = t;
4144   }
4145
4146   /* size is checked already == 2 */
4147 //  size = AOP_SIZE(result);
4148
4149   if (AOP_TYPE(right) == AOP_LIT) {
4150     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4151       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4152       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4153       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4154   } else {
4155     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4156       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4157       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4158       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4159   }
4160         
4161   pic16_genMult16X16_16(left, right,result);
4162 }
4163
4164 /*-----------------------------------------------------------------*/
4165 /* genMultOneLong : 32 bit multiplication                          */
4166 /*-----------------------------------------------------------------*/
4167 static void genMultOneLong (operand *left,
4168                             operand *right,
4169                             operand *result)
4170 {
4171   FENTRY;
4172   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4173   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4174
4175   /* (if two literals, the value is computed before)
4176    * if one literal, literal on the right */
4177   if (AOP_TYPE(left) == AOP_LIT){
4178     operand *t = right;
4179     right = left;
4180     left = t;
4181   }
4182
4183   /* size is checked already == 4 */
4184 //  size = AOP_SIZE(result);
4185
4186   if (AOP_TYPE(right) == AOP_LIT) {
4187     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4188         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4189         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4190         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4191   } else {
4192     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4193         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4194         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4195         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4196   }
4197         
4198   pic16_genMult32X32_32(left, right,result);
4199 }
4200
4201
4202
4203 /*-----------------------------------------------------------------*/
4204 /* genMult - generates code for multiplication                     */
4205 /*-----------------------------------------------------------------*/
4206 static void genMult (iCode *ic)
4207 {
4208   operand *left = IC_LEFT(ic);
4209   operand *right = IC_RIGHT(ic);
4210   operand *result= IC_RESULT(ic);   
4211
4212     FENTRY;
4213         /* assign the amsops */
4214         pic16_aopOp (left,ic,FALSE);
4215         pic16_aopOp (right,ic,FALSE);
4216         pic16_aopOp (result,ic,TRUE);
4217
4218         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4219
4220         /* special cases first *
4221         * both are bits */
4222         if (AOP_TYPE(left) == AOP_CRY
4223                 && AOP_TYPE(right)== AOP_CRY) {
4224                 genMultbits(left,right,result);
4225           goto release ;
4226         }
4227
4228         /* if both are of size == 1 */
4229         if(AOP_SIZE(left) == 1
4230                 && AOP_SIZE(right) == 1) {
4231                 genMultOneByte(left,right,result);
4232           goto release ;
4233         }
4234
4235         /* if both are of size == 2 */
4236         if(AOP_SIZE(left) == 2
4237                 && AOP_SIZE(right) == 2) {
4238                 genMultOneWord(left, right, result);
4239           goto release;
4240         }
4241         
4242         /* if both are of size == 4 */
4243         if(AOP_SIZE(left) == 4
4244                 && AOP_SIZE(right) == 4) {
4245                 genMultOneLong(left, right, result);
4246           goto release;
4247         }
4248         
4249         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4250
4251
4252         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4253         /* should have been converted to function call */
4254         assert(0) ;
4255
4256 release :
4257         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4258         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4259         pic16_freeAsmop(result,NULL,ic,TRUE); 
4260 }
4261
4262 /*-----------------------------------------------------------------*/
4263 /* genDivbits :- division of bits                                  */
4264 /*-----------------------------------------------------------------*/
4265 static void genDivbits (operand *left, 
4266                         operand *right, 
4267                         operand *result)
4268 {
4269   char *l;
4270
4271     FENTRY;
4272     /* the result must be bit */    
4273     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4274     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4275
4276     MOVA(l);    
4277
4278     pic16_emitcode("div","ab");
4279     pic16_emitcode("rrc","a");
4280     pic16_aopPut(AOP(result),"c",0);
4281 }
4282
4283 /*-----------------------------------------------------------------*/
4284 /* genDivOneByte : 8 bit division                                  */
4285 /*-----------------------------------------------------------------*/
4286 static void genDivOneByte (operand *left,
4287                            operand *right,
4288                            operand *result)
4289 {
4290   sym_link *opetype = operandType(result);
4291   char *l ;
4292   symbol *lbl ;
4293   int size,offset;
4294
4295         /* result = divident / divisor
4296          * - divident may be a register or a literal,
4297          * - divisor may be a register or a literal,
4298          * so there are 3 cases (literal / literal is optimized
4299          * by the front-end) to handle.
4300          * In addition we must handle signed and unsigned, which
4301          * result in 6 final different cases -- VR */
4302
4303     FENTRY;
4304     
4305     size = AOP_SIZE(result) - 1;
4306     offset = 1;
4307     /* signed or unsigned */
4308     if (SPEC_USIGN(opetype)) {
4309       pCodeOp *pct1,    /* count */
4310                 *pct2,  /* reste */
4311                 *pct3;  /* temp */
4312       symbol *label1, *label2, *label3;;
4313
4314
4315         /* unsigned is easy */
4316
4317         pct1 = pic16_popGetTempReg(1);
4318         pct2 = pic16_popGetTempReg(1);
4319         pct3 = pic16_popGetTempReg(1);
4320         
4321         label1 = newiTempLabel(NULL);
4322         label2 = newiTempLabel(NULL);
4323         label3 = newiTempLabel(NULL);
4324
4325         /* the following algorithm is extracted from divuint.c */
4326
4327         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4328         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4329         
4330         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4331
4332         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4333         
4334         pic16_emitpLabel(label1->key);
4335         
4336         emitCLRC;
4337         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4338
4339
4340         emitCLRC;
4341         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4342         
4343
4344         emitSKPNC;
4345         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4346         
4347         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4348         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4349         
4350         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4351         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4352         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4353         
4354         pic16_emitpLabel( label3->key );
4355         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4356         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4357         
4358         
4359
4360         pic16_emitpLabel(label2->key);
4361         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4362         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4363         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4364         
4365         /* result is in wreg */
4366         if(AOP_TYPE(result) != AOP_ACC)
4367                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4368
4369         pic16_popReleaseTempReg( pct3, 1);
4370         pic16_popReleaseTempReg( pct2, 1);
4371         pic16_popReleaseTempReg( pct1, 1);
4372
4373         return ;
4374     }
4375
4376     /* signed is a little bit more difficult */
4377
4378     /* save the signs of the operands */
4379     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4380     MOVA(l);    
4381     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4382     pic16_emitcode("push","acc"); /* save it on the stack */
4383
4384     /* now sign adjust for both left & right */
4385     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4386     MOVA(l);       
4387     lbl = newiTempLabel(NULL);
4388     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4389     pic16_emitcode("cpl","a");   
4390     pic16_emitcode("inc","a");
4391     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4392     pic16_emitcode("mov","b,a");
4393
4394     /* sign adjust left side */
4395     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4396     MOVA(l);
4397
4398     lbl = newiTempLabel(NULL);
4399     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4400     pic16_emitcode("cpl","a");
4401     pic16_emitcode("inc","a");
4402     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4403
4404     /* now the division */
4405     pic16_emitcode("div","ab");
4406     /* we are interested in the lower order
4407     only */
4408     pic16_emitcode("mov","b,a");
4409     lbl = newiTempLabel(NULL);
4410     pic16_emitcode("pop","acc");   
4411     /* if there was an over flow we don't 
4412     adjust the sign of the result */
4413     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4414     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4415     CLRC;
4416     pic16_emitcode("clr","a");
4417     pic16_emitcode("subb","a,b");
4418     pic16_emitcode("mov","b,a");
4419     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4420
4421     /* now we are done */
4422     pic16_aopPut(AOP(result),"b",0);
4423     if(size > 0){
4424         pic16_emitcode("mov","c,b.7");
4425         pic16_emitcode("subb","a,acc");   
4426     }
4427     while (size--)
4428         pic16_aopPut(AOP(result),"a",offset++);
4429
4430 }
4431
4432 /*-----------------------------------------------------------------*/
4433 /* genDiv - generates code for division                            */
4434 /*-----------------------------------------------------------------*/
4435 static void genDiv (iCode *ic)
4436 {
4437     operand *left = IC_LEFT(ic);
4438     operand *right = IC_RIGHT(ic);
4439     operand *result= IC_RESULT(ic);   
4440
4441
4442         /* Division is a very lengthy algorithm, so it is better
4443          * to call support routines than inlining algorithm.
4444          * Division functions written here just in case someone
4445          * wants to inline and not use the support libraries -- VR */
4446
4447     FENTRY;
4448     
4449     /* assign the amsops */
4450     pic16_aopOp (left,ic,FALSE);
4451     pic16_aopOp (right,ic,FALSE);
4452     pic16_aopOp (result,ic,TRUE);
4453
4454     /* special cases first */
4455     /* both are bits */
4456     if (AOP_TYPE(left) == AOP_CRY &&
4457         AOP_TYPE(right)== AOP_CRY) {
4458         genDivbits(left,right,result);
4459         goto release ;
4460     }
4461
4462     /* if both are of size == 1 */
4463     if (AOP_SIZE(left) == 1 &&
4464         AOP_SIZE(right) == 1 ) {
4465         genDivOneByte(left,right,result);
4466         goto release ;
4467     }
4468
4469     /* should have been converted to function call */
4470     assert(0);
4471 release :
4472     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4473     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4474     pic16_freeAsmop(result,NULL,ic,TRUE); 
4475 }
4476
4477 /*-----------------------------------------------------------------*/
4478 /* genModbits :- modulus of bits                                   */
4479 /*-----------------------------------------------------------------*/
4480 static void genModbits (operand *left, 
4481                         operand *right, 
4482                         operand *result)
4483 {
4484   char *l;
4485
4486     FENTRY;  
4487     
4488     werror(W_POSSBUG2, __FILE__, __LINE__);
4489     /* the result must be bit */    
4490     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4491     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4492
4493     MOVA(l);       
4494
4495     pic16_emitcode("div","ab");
4496     pic16_emitcode("mov","a,b");
4497     pic16_emitcode("rrc","a");
4498     pic16_aopPut(AOP(result),"c",0);
4499 }
4500
4501 /*-----------------------------------------------------------------*/
4502 /* genModOneByte : 8 bit modulus                                   */
4503 /*-----------------------------------------------------------------*/
4504 static void genModOneByte (operand *left,
4505                            operand *right,
4506                            operand *result)
4507 {
4508   sym_link *opetype = operandType(result);
4509   char *l ;
4510   symbol *lbl ;
4511
4512     FENTRY;
4513     werror(W_POSSBUG2, __FILE__, __LINE__);
4514
4515     /* signed or unsigned */
4516     if (SPEC_USIGN(opetype)) {
4517         /* unsigned is easy */
4518         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4519         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4520         MOVA(l);    
4521         pic16_emitcode("div","ab");
4522         pic16_aopPut(AOP(result),"b",0);
4523         return ;
4524     }
4525
4526     /* signed is a little bit more difficult */
4527
4528     /* save the signs of the operands */
4529     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4530     MOVA(l);
4531
4532     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533     pic16_emitcode("push","acc"); /* save it on the stack */
4534
4535     /* now sign adjust for both left & right */
4536     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4537     MOVA(l);
4538
4539     lbl = newiTempLabel(NULL);
4540     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4541     pic16_emitcode("cpl","a");   
4542     pic16_emitcode("inc","a");
4543     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4544     pic16_emitcode("mov","b,a"); 
4545
4546     /* sign adjust left side */
4547     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4548     MOVA(l);
4549
4550     lbl = newiTempLabel(NULL);
4551     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4552     pic16_emitcode("cpl","a");   
4553     pic16_emitcode("inc","a");
4554     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4555
4556     /* now the multiplication */
4557     pic16_emitcode("div","ab");
4558     /* we are interested in the lower order
4559     only */
4560     lbl = newiTempLabel(NULL);
4561     pic16_emitcode("pop","acc");   
4562     /* if there was an over flow we don't 
4563     adjust the sign of the result */
4564     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4565     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4566     CLRC ;
4567     pic16_emitcode("clr","a");
4568     pic16_emitcode("subb","a,b");
4569     pic16_emitcode("mov","b,a");
4570     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4571
4572     /* now we are done */
4573     pic16_aopPut(AOP(result),"b",0);
4574
4575 }
4576
4577 /*-----------------------------------------------------------------*/
4578 /* genMod - generates code for division                            */
4579 /*-----------------------------------------------------------------*/
4580 static void genMod (iCode *ic)
4581 {
4582   operand *left = IC_LEFT(ic);
4583   operand *right = IC_RIGHT(ic);
4584   operand *result= IC_RESULT(ic);  
4585
4586     FENTRY;
4587     
4588     /* assign the amsops */
4589     pic16_aopOp (left,ic,FALSE);
4590     pic16_aopOp (right,ic,FALSE);
4591     pic16_aopOp (result,ic,TRUE);
4592
4593     /* special cases first */
4594     /* both are bits */
4595     if (AOP_TYPE(left) == AOP_CRY &&
4596         AOP_TYPE(right)== AOP_CRY) {
4597         genModbits(left,right,result);
4598         goto release ;
4599     }
4600
4601     /* if both are of size == 1 */
4602     if (AOP_SIZE(left) == 1 &&
4603         AOP_SIZE(right) == 1 ) {
4604         genModOneByte(left,right,result);
4605         goto release ;
4606     }
4607
4608     /* should have been converted to function call */
4609     assert(0);
4610
4611 release :
4612     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4613     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4614     pic16_freeAsmop(result,NULL,ic,TRUE); 
4615 }
4616
4617 /*-----------------------------------------------------------------*/
4618 /* genIfxJump :- will create a jump depending on the ifx           */
4619 /*-----------------------------------------------------------------*/
4620 /*
4621   note: May need to add parameter to indicate when a variable is in bit space.
4622 */
4623 static void genIfxJump (iCode *ic, char *jval)
4624 {
4625   FENTRY;
4626   
4627     /* if true label then we jump if condition
4628     supplied is true */
4629     if ( IC_TRUE(ic) ) {
4630
4631         if(strcmp(jval,"a") == 0)
4632           emitSKPZ;
4633         else if (strcmp(jval,"c") == 0)
4634           emitSKPNC;
4635         else {
4636           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4637           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4638         }
4639
4640         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4641         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4642
4643     }
4644     else {
4645         /* false label is present */
4646         if(strcmp(jval,"a") == 0)
4647           emitSKPNZ;
4648         else if (strcmp(jval,"c") == 0)
4649           emitSKPC;
4650         else {
4651           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4652           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4653         }
4654
4655         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4656         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4657
4658     }
4659
4660
4661     /* mark the icode as generated */
4662     ic->generated = 1;
4663 }
4664
4665 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4666 {
4667   FENTRY;
4668   
4669     /* if true label then we jump if condition
4670     supplied is true */
4671     if ( IC_TRUE(ic) ) {
4672       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4673       pic16_emitpcode(POC_BTFSC, jop);
4674
4675       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4676       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4677
4678     } else {
4679       /* false label is present */
4680       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4681       pic16_emitpcode(POC_BTFSS, jop);
4682           
4683       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4684       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4685     }
4686
4687
4688     /* mark the icode as generated */
4689     ic->generated = 1;
4690 }
4691
4692 #if 0
4693 // not needed ATM
4694
4695 /*-----------------------------------------------------------------*/
4696 /* genSkip                                                         */
4697 /*-----------------------------------------------------------------*/
4698 static void genSkip(iCode *ifx,int status_bit)
4699 {
4700   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4701   if(!ifx)
4702     return;
4703
4704   if ( IC_TRUE(ifx) ) {
4705     switch(status_bit) {
4706     case 'z':
4707       emitSKPNZ;
4708       break;
4709
4710     case 'c':
4711       emitSKPNC;
4712       break;
4713
4714     case 'd':
4715       emitSKPDC;
4716       break;
4717
4718     }
4719
4720     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4721     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4722
4723   } else {
4724
4725     switch(status_bit) {
4726
4727     case 'z':
4728       emitSKPZ;
4729       break;
4730
4731     case 'c':
4732       emitSKPC;
4733       break;
4734
4735     case 'd':
4736       emitSKPDC;
4737       break;
4738     }
4739     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4740     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4741
4742   }
4743
4744 }
4745 #endif
4746
4747 /*-----------------------------------------------------------------*/
4748 /* genSkipc                                                        */
4749 /*-----------------------------------------------------------------*/
4750 static void genSkipc(resolvedIfx *rifx)
4751 {
4752   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4753   
4754   if(!rifx)
4755     return;
4756
4757   if(rifx->condition)
4758     emitSKPNC;
4759   else
4760     emitSKPC;
4761
4762   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4763   rifx->generated = 1;
4764 }
4765
4766 #if !(USE_SIMPLE_GENCMP)
4767 /*-----------------------------------------------------------------*/
4768 /* genSkipz2                                                       */
4769 /*-----------------------------------------------------------------*/
4770 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4771 {
4772   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4773   
4774   if(!rifx)
4775     return;
4776
4777   if( (rifx->condition ^ invert_condition) & 1)
4778     emitSKPZ;
4779   else
4780     emitSKPNZ;
4781
4782   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4783   rifx->generated = 1;
4784 }
4785 #endif
4786
4787 #if 0
4788 /*-----------------------------------------------------------------*/
4789 /* genSkipz                                                        */
4790 /*-----------------------------------------------------------------*/
4791 static void genSkipz(iCode *ifx, int condition)
4792 {
4793   if(!ifx)
4794     return;
4795
4796   if(condition)
4797     emitSKPNZ;
4798   else
4799     emitSKPZ;
4800
4801   if ( IC_TRUE(ifx) )
4802     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4803   else
4804     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4805
4806   if ( IC_TRUE(ifx) )
4807     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4808   else
4809     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4810
4811 }
4812 #endif
4813
4814 #if !(USE_SIMPLE_GENCMP)
4815 /*-----------------------------------------------------------------*/
4816 /* genSkipCond                                                     */
4817 /*-----------------------------------------------------------------*/
4818 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4819 {
4820   if(!rifx)
4821     return;
4822
4823   if(rifx->condition)
4824     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4825   else
4826     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4827
4828
4829   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4830   rifx->generated = 1;
4831 }
4832 #endif
4833
4834 #if 0
4835 /*-----------------------------------------------------------------*/
4836 /* genChkZeroes :- greater or less than comparison                 */
4837 /*     For each byte in a literal that is zero, inclusive or the   */
4838 /*     the corresponding byte in the operand with W                */
4839 /*     returns true if any of the bytes are zero                   */
4840 /*-----------------------------------------------------------------*/
4841 static int genChkZeroes(operand *op, int lit,  int size)
4842 {
4843
4844   int i;
4845   int flag =1;
4846
4847   while(size--) {
4848     i = (lit >> (size*8)) & 0xff;
4849
4850     if(i==0) {
4851       if(flag) 
4852         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4853       else
4854         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4855       flag = 0;
4856     }
4857   }
4858
4859   return (flag==0);
4860 }
4861 #endif
4862
4863
4864 /*-----------------------------------------------------------------*/
4865 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4866 /*                  aop (if it's NOT a literal) or from lit (if    */
4867 /*                  aop is a literal)                              */
4868 /*-----------------------------------------------------------------*/
4869 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4870   if (aop->type == AOP_LIT) {
4871     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4872   } else {
4873     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4874   }
4875 }
4876
4877 /*-----------------------------------------------------------------*/
4878 /* genCmp :- greater or less than comparison                       */
4879 /*-----------------------------------------------------------------*/
4880
4881 #if USE_SIMPLE_GENCMP           /* { */
4882
4883 /* genCmp performs a left < right comparison, stores
4884  * the outcome in result (if != NULL) and generates
4885  * control flow code for the ifx (if != NULL).
4886  *
4887  * This version leaves in sequences like
4888  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4889  * which should be optmized by the peephole
4890  * optimizer - RN 2005-01-01 */
4891 static void genCmp (operand *left,operand *right,
4892                     operand *result, iCode *ifx, int sign)
4893 {
4894   resolvedIfx rIfx;
4895   int size;
4896   int offs;
4897   symbol *templbl;
4898   operand *dummy;
4899   unsigned long lit;
4900   unsigned long mask;
4901   int performedLt;
4902
4903   FENTRY;
4904   
4905   assert (left && right);
4906   assert (AOP_SIZE(left) == AOP_SIZE(right));
4907
4908   size = AOP_SIZE(right) - 1;
4909   mask = (0x100UL << (size*8)) - 1;
4910   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4911   performedLt = 1;
4912   templbl = NULL;
4913   lit = 0;
4914   
4915   resolveIfx (&rIfx, ifx);
4916
4917   /* handle for special cases */
4918   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4919       return;
4920
4921   /**********************************************************************
4922    * handle bits - bit compares are promoted to int compares seemingly! *
4923    **********************************************************************/
4924 #if 0
4925   // THIS IS COMPLETELY UNTESTED!
4926   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4927     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4928     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4929     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4930
4931     emitSETC;
4932     // 1 < {0,1} is false --> clear C by skipping the next instruction
4933     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4934     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4935     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4936     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4937     emitCLRC; // only skipped for left=0 && right=1
4938
4939     goto correct_result_in_carry;
4940   } // if
4941 #endif
4942
4943   /*************************************************
4944    * make sure that left is register (or the like) *
4945    *************************************************/
4946   if (!isAOP_REGlike(left)) {
4947     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
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 why 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, i.e. "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       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4984       if (lit == 0) {
4985         // unsigned left < 0? always false
4986         if (performedLt) emitCLRC; else emitSETC;
4987         goto correct_result_in_carry;
4988       }
4989     } else {
4990       // signed comparison to a literal
4991       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4992       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4993         // signed left < 0x80000000? always false
4994         if (performedLt) emitCLRC; else emitSETC;
4995         goto correct_result_in_carry;
4996       } else if (lit == 0) {
4997         // compare left < 0; set CARRY if SIGNBIT(left) is set
4998         if (performedLt) emitSETC; else emitCLRC;
4999         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5000         if (performedLt) emitCLRC; else emitSETC;
5001         goto correct_result_in_carry;
5002       }
5003     } // if (!sign)
5004   } // right is literal
5005
5006   /*************************************************
5007    * perform a general case comparison             *
5008    * make sure we get CARRY==1 <==> left >= right  *
5009    *************************************************/
5010   // compare most significant bytes
5011   //DEBUGpc ("comparing bytes at offset %d", size);
5012   if (!sign) {
5013     // unsigned comparison
5014     mov2w_regOrLit (AOP(right), lit, size);
5015     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5016   } else {
5017     // signed comparison
5018     // (add 2^n to both operands then perform an unsigned comparison)
5019     if (isAOP_LIT(right)) {
5020       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5021       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5022
5023       if (litbyte == 0x80) {
5024         // left >= 0x80 -- always true, but more bytes to come
5025         pic16_mov2w (AOP(left), size);
5026         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5027         emitSETC;
5028       } else {
5029         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5030         pic16_mov2w (AOP(left), size);
5031         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5032         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5033       } // if
5034     } else {
5035       /* using PRODL as a temporary register here */
5036       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5037       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5038       pic16_mov2w (AOP(left), size);
5039       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5040       pic16_emitpcode (POC_MOVWF, pctemp);
5041       pic16_mov2w (AOP(right), size);
5042       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5043       pic16_emitpcode (POC_SUBFW, pctemp);
5044       //pic16_popReleaseTempReg(pctemp, 1);
5045     }
5046   } // if (!sign)
5047
5048   // compare remaining bytes (treat as unsigned case from above)
5049   templbl = newiTempLabel ( NULL );
5050   offs = size;
5051   while (offs--) {
5052     //DEBUGpc ("comparing bytes at offset %d", offs);
5053     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5054     mov2w_regOrLit (AOP(right), lit, offs);
5055     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5056   } // while (offs)
5057   pic16_emitpLabel (templbl->key);
5058   goto result_in_carry;
5059
5060 result_in_carry:
5061   
5062   /****************************************************
5063    * now CARRY contains the result of the comparison: *
5064    * SUBWF sets CARRY iff                             *
5065    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5066    * (F=left, W=right)                                *
5067    ****************************************************/
5068
5069   if (performedLt) {
5070     if (result && AOP_TYPE(result) != AOP_CRY) {
5071       // value will be stored
5072       emitTOGC;
5073     } else {
5074       // value wil only be used in the following genSkipc()
5075       rIfx.condition ^= 1;
5076     }
5077   } // if
5078
5079 correct_result_in_carry:
5080
5081   // assign result to variable (if neccessary)
5082   if (result && AOP_TYPE(result) != AOP_CRY) {
5083     //DEBUGpc ("assign result");
5084     size = AOP_SIZE(result);
5085     while (size--) {
5086       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5087     } // while
5088     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5089   } // if (result)
5090
5091   // perform conditional jump
5092   if (ifx) {
5093     //DEBUGpc ("generate control flow");
5094     genSkipc (&rIfx);
5095     ifx->generated = 1;
5096   } // if
5097 }
5098
5099 #elif 1         /* } */
5100                 /* { */
5101       /* original code */
5102 static void genCmp (operand *left,operand *right,
5103                     operand *result, iCode *ifx, int sign)
5104 {
5105   int size; //, offset = 0 ;
5106   unsigned long lit = 0L,i = 0;
5107   resolvedIfx rFalseIfx;
5108   //  resolvedIfx rTrueIfx;
5109   symbol *truelbl;
5110   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5111 /*
5112   if(ifx) {
5113     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5114     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5115   }
5116 */
5117
5118   FENTRY;
5119   
5120   resolveIfx(&rFalseIfx,ifx);
5121   truelbl  = newiTempLabel(NULL);
5122   size = max(AOP_SIZE(left),AOP_SIZE(right));
5123
5124   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5125
5126 #define _swapp
5127
5128   /* if literal is on the right then swap with left */
5129   if ((AOP_TYPE(right) == AOP_LIT)) {
5130     operand *tmp = right ;
5131     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5132     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5133 #ifdef _swapp
5134
5135     lit = (lit - 1) & mask;
5136     right = left;
5137     left = tmp;
5138     rFalseIfx.condition ^= 1;
5139 #endif
5140
5141   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5142     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5143   }
5144
5145
5146   //if(IC_TRUE(ifx) == NULL)
5147   /* if left & right are bit variables */
5148   if (AOP_TYPE(left) == AOP_CRY &&
5149       AOP_TYPE(right) == AOP_CRY ) {
5150     assert (0 && "bit variables used in genCmp");
5151     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5152     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5153   } else {
5154     /* subtract right from left if at the
5155        end the carry flag is set then we know that
5156        left is greater than right */
5157
5158     symbol *lbl  = newiTempLabel(NULL);
5159
5160 #if 0
5161         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5162                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5163 #endif
5164
5165 #ifndef _swapp
5166     if(AOP_TYPE(right) == AOP_LIT) {
5167
5168       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5169
5170       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5171
5172       /* special cases */
5173
5174       if(lit == 0) {
5175
5176         if(sign != 0) 
5177           genSkipCond(&rFalseIfx,left,size-1,7);
5178         else 
5179           /* no need to compare to 0...*/
5180           /* NOTE: this is a de-generate compare that most certainly 
5181            *       creates some dead code. */
5182           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5183
5184         if(ifx) ifx->generated = 1;
5185         return;
5186
5187       }
5188       size--;
5189
5190       if(size == 0) {
5191         //i = (lit >> (size*8)) & 0xff;
5192         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5193         
5194         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5195
5196         i = ((0-lit) & 0xff);
5197         if(sign) {
5198           if( i == 0x81) { 
5199             /* lit is 0x7f, all signed chars are less than
5200              * this except for 0x7f itself */
5201             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5202             genSkipz2(&rFalseIfx,0);
5203           } else {
5204             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5205             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5206             genSkipc(&rFalseIfx);
5207           }
5208
5209         } else {
5210           if(lit == 1) {
5211             genSkipz2(&rFalseIfx,1);
5212           } else {
5213             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5214             genSkipc(&rFalseIfx);
5215           }
5216         }
5217
5218         if(ifx) ifx->generated = 1;
5219         return;
5220       }
5221
5222       /* chars are out of the way. now do ints and longs */
5223
5224
5225       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5226         
5227       /* special cases */
5228
5229       if(sign) {
5230
5231         if(lit == 0) {
5232           genSkipCond(&rFalseIfx,left,size,7);
5233           if(ifx) ifx->generated = 1;
5234           return;
5235         }
5236
5237         if(lit <0x100) {
5238           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5239
5240           //rFalseIfx.condition ^= 1;
5241           //genSkipCond(&rFalseIfx,left,size,7);
5242           //rFalseIfx.condition ^= 1;
5243
5244           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5245           if(rFalseIfx.condition)
5246             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5247           else
5248             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5249
5250           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5251           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5252           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5253
5254           while(size > 1)
5255             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5256
5257           if(rFalseIfx.condition) {
5258             emitSKPZ;
5259             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5260
5261           } else {
5262             emitSKPNZ;
5263           }
5264
5265           genSkipc(&rFalseIfx);
5266           pic16_emitpLabel(truelbl->key);
5267           if(ifx) ifx->generated = 1;
5268           return;
5269
5270         }
5271
5272         if(size == 1) {
5273
5274           if( (lit & 0xff) == 0) {
5275             /* lower byte is zero */
5276             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5277             i = ((lit >> 8) & 0xff) ^0x80;
5278             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5279             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5280             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5281             genSkipc(&rFalseIfx);
5282
5283
5284             if(ifx) ifx->generated = 1;
5285             return;
5286
5287           }
5288         } else {
5289           /* Special cases for signed longs */
5290           if( (lit & 0xffffff) == 0) {
5291             /* lower byte is zero */
5292             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5293             i = ((lit >> 8*3) & 0xff) ^0x80;
5294             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5297             genSkipc(&rFalseIfx);
5298
5299
5300             if(ifx) ifx->generated = 1;
5301             return;
5302
5303           }
5304
5305         }
5306
5307
5308         if(lit & (0x80 << (size*8))) {
5309           /* lit is negative */
5310           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5311
5312           //genSkipCond(&rFalseIfx,left,size,7);
5313
5314           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5315
5316           if(rFalseIfx.condition)
5317             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5318           else
5319             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5320
5321
5322         } else {
5323           /* lit is positive */
5324           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5325           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5326           if(rFalseIfx.condition)
5327             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5328           else
5329             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5330
5331         }
5332
5333         /*
5334           This works, but is only good for ints.
5335           It also requires a "known zero" register.
5336           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5337           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5338           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5339           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5340           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5341           genSkipc(&rFalseIfx);
5342
5343           pic16_emitpLabel(truelbl->key);
5344           if(ifx) ifx->generated = 1;
5345           return;
5346         **/
5347           
5348         /* There are no more special cases, so perform a general compare */
5349   
5350         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5351         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5352
5353         while(size--) {
5354
5355           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5356           emitSKPNZ;
5357           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5358         }
5359         //rFalseIfx.condition ^= 1;
5360         genSkipc(&rFalseIfx);
5361
5362         pic16_emitpLabel(truelbl->key);
5363
5364         if(ifx) ifx->generated = 1;
5365         return;
5366
5367
5368       }
5369
5370
5371       /* sign is out of the way. So now do an unsigned compare */
5372       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5373
5374
5375       /* General case - compare to an unsigned literal on the right.*/
5376
5377       i = (lit >> (size*8)) & 0xff;
5378       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5379       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5380       while(size--) {
5381         i = (lit >> (size*8)) & 0xff;
5382
5383         if(i) {
5384           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5385           emitSKPNZ;
5386           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5387         } else {
5388           /* this byte of the lit is zero, 
5389            *if it's not the last then OR in the variable */
5390           if(size)
5391             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5392         }
5393       }
5394
5395
5396       pic16_emitpLabel(lbl->key);
5397 //      pic16_emitpLabel(truelbl->key);
5398       //if(emitFinalCheck)
5399       genSkipc(&rFalseIfx);
5400       if(sign)
5401         pic16_emitpLabel(truelbl->key);
5402
5403       if(ifx) ifx->generated = 1;
5404       return;
5405
5406
5407     }
5408 #endif  // _swapp
5409
5410     if(AOP_TYPE(left) == AOP_LIT) {
5411       //symbol *lbl = newiTempLabel(NULL);
5412
5413       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5414
5415
5416       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5417
5418       /* Special cases */
5419       if((lit == 0) && (sign == 0)){
5420
5421         size--;
5422         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5423         while(size) 
5424           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5425
5426         genSkipz2(&rFalseIfx,0);
5427         if(ifx) ifx->generated = 1;
5428         return;
5429       }
5430
5431       if(size==1) {
5432         /* Special cases */
5433         lit &= 0xff;
5434         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5435           /* degenerate compare can never be true */
5436           if(rFalseIfx.condition == 0)
5437             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5438
5439           if(ifx) ifx->generated = 1;
5440           return;
5441         }
5442
5443         if(sign) {
5444           /* signed comparisons to a literal byte */
5445
5446           int lp1 = (lit+1) & 0xff;
5447
5448           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5449           switch (lp1) {
5450           case 0:
5451             rFalseIfx.condition ^= 1;
5452             genSkipCond(&rFalseIfx,right,0,7);
5453             break;
5454           case 0x7f:
5455             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5456             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5457             genSkipz2(&rFalseIfx,1);
5458             break;
5459           default:
5460             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5461             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5462             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5463             rFalseIfx.condition ^= 1;
5464             genSkipc(&rFalseIfx);
5465             break;
5466           }
5467         } else {
5468           /* unsigned comparisons to a literal byte */
5469
5470           switch(lit & 0xff ) {
5471           case 0:
5472             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5473             genSkipz2(&rFalseIfx,0);
5474             break;
5475           case 0x7f:
5476             rFalseIfx.condition ^= 1;
5477             genSkipCond(&rFalseIfx,right,0,7);
5478             break;
5479
5480           default:
5481             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5482             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5483             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5484             rFalseIfx.condition ^= 1;
5485             if (AOP_TYPE(result) == AOP_CRY)
5486               genSkipc(&rFalseIfx);
5487             else {
5488               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5489               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5490             }         
5491             break;
5492           }
5493         }
5494
5495         if(ifx) ifx->generated = 1;
5496         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5497                 goto check_carry;
5498         return;
5499
5500       } else {
5501
5502         /* Size is greater than 1 */
5503
5504         if(sign) {
5505           int lp1 = lit+1;
5506
5507           size--;
5508
5509           if(lp1 == 0) {
5510             /* this means lit = 0xffffffff, or -1 */
5511
5512
5513             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5514             rFalseIfx.condition ^= 1;
5515             genSkipCond(&rFalseIfx,right,size,7);
5516             if(ifx) ifx->generated = 1;
5517
5518             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5519               goto check_carry;
5520
5521             return;
5522           }
5523
5524           if(lit == 0) {
5525             int s = size;
5526
5527             if(rFalseIfx.condition) {
5528               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5529               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5530             }
5531
5532             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5533             while(size--)
5534               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5535
5536
5537             emitSKPZ;
5538             if(rFalseIfx.condition) {
5539               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5540               pic16_emitpLabel(truelbl->key);
5541             }else {
5542               rFalseIfx.condition ^= 1;
5543               genSkipCond(&rFalseIfx,right,s,7);
5544             }
5545
5546             if(ifx) ifx->generated = 1;
5547
5548             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5549               goto check_carry;
5550
5551             return;
5552           }
5553
5554           if((size == 1) &&  (0 == (lp1&0xff))) {
5555             /* lower byte of signed word is zero */
5556             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5557             i = ((lp1 >> 8) & 0xff) ^0x80;
5558             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5559             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5560             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5561
5562             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5563               emitTOGC;
5564               if(ifx) ifx->generated = 1;
5565               goto check_carry;
5566             } else {
5567               rFalseIfx.condition ^= 1;
5568               genSkipc(&rFalseIfx);
5569               if(ifx) ifx->generated = 1;
5570             }
5571
5572             return;
5573           }
5574
5575           if(lit & (0x80 << (size*8))) {
5576             /* Lit is less than zero */
5577             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5578             //rFalseIfx.condition ^= 1;
5579             //genSkipCond(&rFalseIfx,left,size,7);
5580             //rFalseIfx.condition ^= 1;
5581             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5582             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5583
5584             if(rFalseIfx.condition)
5585               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5586             else
5587               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5588
5589
5590           } else {
5591             /* Lit is greater than or equal to zero */
5592             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5593             //rFalseIfx.condition ^= 1;
5594             //genSkipCond(&rFalseIfx,right,size,7);
5595             //rFalseIfx.condition ^= 1;
5596
5597             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5598             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5599
5600             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5601             if(rFalseIfx.condition)
5602               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5603             else
5604               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5605
5606           }
5607
5608           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5609           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5610
5611           while(size--) {
5612
5613             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5614             emitSKPNZ;
5615             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5616           }
5617           rFalseIfx.condition ^= 1;
5618           //rFalseIfx.condition = 1;
5619           genSkipc(&rFalseIfx);
5620
5621           pic16_emitpLabel(truelbl->key);
5622
5623           if(ifx) ifx->generated = 1;
5624
5625
5626           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5627             goto check_carry;
5628
5629           return;
5630           // end of if (sign)
5631         } else {
5632
5633           /* compare word or long to an unsigned literal on the right.*/
5634
5635
5636           size--;
5637           if(lit < 0xff) {
5638             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5639             switch (lit) {
5640             case 0:
5641               break; /* handled above */
5642 /*
5643             case 0xff:
5644               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5645               while(size--)
5646                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5647               genSkipz2(&rFalseIfx,0);
5648               break;
5649 */
5650             default:
5651               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5652               while(--size)
5653                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5654
5655               emitSKPZ;
5656               if(rFalseIfx.condition)
5657                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5658               else
5659                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5660
5661
5662               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5663               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5664
5665               rFalseIfx.condition ^= 1;
5666               genSkipc(&rFalseIfx);
5667             }
5668
5669             pic16_emitpLabel(truelbl->key);
5670
5671             if(ifx) ifx->generated = 1;
5672
5673             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5674               goto check_carry;
5675
5676             return;
5677           }
5678
5679
5680           lit++;
5681           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5682           i = (lit >> (size*8)) & 0xff;
5683
5684           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5685           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5686
5687           while(size--) {
5688             i = (lit >> (size*8)) & 0xff;
5689
5690             if(i) {
5691               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5692               emitSKPNZ;
5693               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5694             } else {
5695               /* this byte of the lit is zero, 
5696                * if it's not the last then OR in the variable */
5697               if(size)
5698                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5699             }
5700           }
5701
5702
5703           pic16_emitpLabel(lbl->key);
5704
5705           rFalseIfx.condition ^= 1;
5706
5707           genSkipc(&rFalseIfx);
5708         }
5709
5710         if(sign)
5711           pic16_emitpLabel(truelbl->key);
5712         if(ifx) ifx->generated = 1;
5713
5714             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5715               goto check_carry;
5716
5717         return;
5718       }
5719     }
5720     /* Compare two variables */
5721
5722     DEBUGpic16_emitcode(";sign","%d",sign);
5723
5724     size--;
5725     if(sign) {
5726       /* Sigh. thus sucks... */
5727       if(size) {
5728         pCodeOp *pctemp;
5729         
5730         pctemp = pic16_popGetTempReg(1);
5731         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5732         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5734         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5735         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5736         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5737         pic16_popReleaseTempReg(pctemp, 1);
5738       } else {
5739         /* Signed char comparison */
5740         /* Special thanks to Nikolai Golovchenko for this snippet */
5741         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5742         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5743         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5744         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5745         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5746         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5747
5748         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5749         genSkipc(&rFalseIfx);
5750           
5751         if(ifx) ifx->generated = 1;
5752
5753             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5754               goto check_carry;
5755
5756         return;
5757       }
5758
5759     } else {
5760
5761       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5762       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5763     }
5764
5765
5766     /* The rest of the bytes of a multi-byte compare */
5767     while (size) {
5768
5769       emitSKPZ;
5770       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5771       size--;
5772
5773       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5774       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5775
5776
5777     }
5778
5779     pic16_emitpLabel(lbl->key);
5780
5781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5782     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5783         (AOP_TYPE(result) == AOP_REG)) {
5784       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5785       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5786     } else {
5787       genSkipc(&rFalseIfx);
5788     }         
5789     //genSkipc(&rFalseIfx);
5790     if(ifx) ifx->generated = 1;
5791
5792
5793             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5794               goto check_carry;
5795
5796     return;
5797
5798   }
5799
5800 check_carry:
5801   if ((AOP_TYPE(result) != AOP_CRY) 
5802         && AOP_SIZE(result)) {
5803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5804
5805     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5806
5807     pic16_outBitC(result);
5808   } else {
5809     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5810     /* if the result is used in the next
5811        ifx conditional branch then generate
5812        code a little differently */
5813     if (ifx )
5814       genIfxJump (ifx,"c");
5815     else
5816       pic16_outBitC(result);
5817     /* leave the result in acc */
5818   }
5819
5820 }
5821
5822 #elif 0 /* VR version of genCmp() */    /* } else { */
5823
5824 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5825 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5826         operand *result, int offset, int invert_op)
5827 {
5828   /* add code here */
5829   
5830   /* check condition, > or < ?? */
5831   if(rIfx->condition != 0)invert_op ^= 1;
5832   
5833   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5834
5835   if(!ifx)invert_op ^= 1;
5836
5837   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5838       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5839   
5840   /* do selection */
5841   if(!invert_op)return POC_CPFSGT;
5842   else return POC_CPFSLT;
5843 }
5844
5845 static int compareAopfirstpass=1;
5846
5847 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5848             operand *oper, int offset, operand *result,
5849             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5850             symbol *tlbl)
5851 {
5852   int op;
5853   symbol *truelbl;
5854
5855   /* invert if there is a result to be loaded, in order to fit,
5856    * SETC/CLRC sequence */
5857   if(AOP_SIZE(result))invert_op ^= 1;
5858
5859 //  if(sign && !offset)invert_op ^= 1;
5860   
5861 //  if(sign)invert_op ^= 1;
5862   
5863   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5864
5865   if(AOP_SIZE(result) && compareAopfirstpass) {
5866     if(!ifx) {
5867       if(pcop2)
5868         pic16_emitpcode(POC_SETF, pcop2);
5869       else
5870         emitSETC;
5871     } else {
5872       if(pcop2)
5873         pic16_emitpcode(POC_CLRF, pcop2);
5874       else
5875         emitCLRC;
5876     }
5877   }
5878
5879   compareAopfirstpass = 0;
5880
5881       /* there is a bug when comparing operands with size > 1,
5882        * because higher bytes can be equal and test should be performed
5883        * to the next lower byte, current algorithm, considers operands
5884        * inequal in these cases! -- VR 20041107 */
5885
5886     
5887   if(pcop)
5888     pic16_emitpcode(op, pcop);
5889   else
5890     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5891
5892
5893   if((!sign || !offset) && AOP_SIZE(result)) {
5894     if(!ifx) {
5895       if(pcop2)
5896         pic16_emitpcode(POC_CLRF, pcop2);
5897         else
5898         emitCLRC;
5899     } else {
5900       if(pcop2)
5901         pic16_emitpcode(POC_SETF, pcop2);
5902       else
5903         emitSETC;
5904     }
5905     
5906     /* don't emit final branch (offset == 0) */
5907     if(offset) {
5908
5909       if(pcop2)
5910         pic16_emitpcode(POC_RRCF, pcop2);
5911
5912       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5913     }
5914   } else {
5915     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5916       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5917             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5918
5919       truelbl = newiTempLabel( NULL );
5920       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5921       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5922         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5923       else
5924         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5925       pic16_emitpLabel(truelbl->key);
5926     } else {
5927       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5928     }
5929   }
5930 }
5931
5932 static void genCmp (operand *left, operand *right,
5933                     operand *result, iCode *ifx, int sign)
5934 {
5935   int size, cmpop=1;
5936   long lit = 0L;
5937   resolvedIfx rFalseIfx;
5938   symbol *falselbl, *tlbl;
5939
5940     FENTRY;
5941     
5942     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5943
5944     resolveIfx(&rFalseIfx, ifx);
5945     size = max(AOP_SIZE(left), AOP_SIZE(right));
5946     
5947     /* if left & right are bit variables */
5948     if(AOP_TYPE(left) == AOP_CRY
5949       && AOP_TYPE(right) == AOP_CRY ) {
5950
5951         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5953         
5954         werror(W_POSSBUG2, __FILE__, __LINE__);
5955         exit(-1);
5956     }
5957     
5958     /* if literal is on the right then swap with left */
5959     if((AOP_TYPE(right) == AOP_LIT)) {
5960       operand *tmp = right ;
5961 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5962
5963         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5964
5965 //      lit = (lit - 1) & mask;
5966         right = left;
5967         left = tmp;
5968         rFalseIfx.condition ^= 1;               /* reverse compare */
5969     } else
5970     if ((AOP_TYPE(left) == AOP_LIT)) {
5971       /* float compares are handled by support functions */
5972       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5973     }
5974
5975     /* actual comparing algorithm */
5976 //    size = AOP_SIZE( right );
5977
5978     falselbl = newiTempLabel( NULL );
5979     if(AOP_TYPE(left) == AOP_LIT) {
5980       /* compare to literal */
5981       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5982       
5983       if(sign) {
5984         pCodeOp *pct, *pct2;
5985         symbol *tlbl1;
5986
5987         /* signed compare */
5988         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5989
5990         /* using PRODL:PRODH as a temporary register here */
5991         pct = pic16_popCopyReg(&pic16_pc_prodl);
5992         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5993         tlbl = newiTempLabel( NULL );
5994         
5995         /* first compare signs:
5996          *  a. if both are positive, compare just like unsigned
5997          *  b. if both are negative, invert cmpop, compare just like unsigned
5998          *  c. if different signs, determine the result directly */
5999
6000         size--;
6001
6002 #if 1
6003         /* { */
6004         tlbl1 = newiTempLabel( NULL );
6005 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6006
6007         if(lit > 0) {
6008
6009           /* literal is zero or positive:
6010            *  a. if carry is zero, too, continue compare,
6011            *  b. if carry is set, then continue depending on cmpop ^ condition:
6012            *    1. '<' return false (literal < variable),
6013            *    2. '>' return true (literal > variable) */
6014 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6015           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6016           
6017           
6018           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6019           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6020         } else 
6021         if(lit < 0) {
6022           
6023           /* literal is negative:
6024            *  a. if carry is set, too, continue compare,
6025            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6026            *    1. '<' return true (literal < variable),
6027            *    2. '>' return false (literal > variable) */
6028 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6029           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6030           
6031           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6032           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6033         }
6034 #if 1
6035         else {
6036           /* lit == 0 */
6037           pic16_emitpcode(POC_BTFSC, 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 #endif
6043         
6044         
6045         pic16_emitpLabel( tlbl1->key );
6046 #endif  /* } */
6047
6048         compareAopfirstpass=1;
6049 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6050 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6051 //        pic16_emitpcode(POC_MOVWF, pct);
6052
6053 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6054         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6055 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6056         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6057
6058         /* generic case */        
6059           while( size-- ) {
6060 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6061 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6062 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6063 //            pic16_emitpcode(POC_MOVWF, pct);
6064
6065 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6066             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6067             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6068 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6069 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6070           }
6071         
6072         if(ifx)ifx->generated = 1;
6073
6074         if(AOP_SIZE(result)) {
6075           pic16_emitpLabel(tlbl->key);
6076           pic16_emitpLabel(falselbl->key);
6077           pic16_outBitOp( result, pct2 );
6078         } else {
6079           pic16_emitpLabel(tlbl->key);
6080         }
6081       } else {
6082
6083         /* unsigned compare */      
6084         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6085     
6086         compareAopfirstpass=1;
6087         while(size--) {
6088           
6089           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6090           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6091
6092         }
6093         if(ifx)ifx->generated = 1;
6094
6095         if(AOP_SIZE(result)) {
6096           pic16_emitpLabel(falselbl->key);
6097           pic16_outBitC( result );
6098         }
6099
6100       }
6101     } else {
6102       /* compare registers */
6103       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6104
6105
6106       if(sign) {
6107         pCodeOp *pct, *pct2;
6108         
6109         /* signed compare */
6110         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6111
6112         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6113         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6114         tlbl = newiTempLabel( NULL );
6115         
6116         compareAopfirstpass=1;
6117
6118         size--;
6119         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6120 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6121         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6122         pic16_emitpcode(POC_MOVWF, pct);
6123
6124         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6125 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6126         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6127
6128         /* WREG already holds left + 0x80 */
6129         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6130         
6131         while( size-- ) {
6132           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6133 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6134           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6135           pic16_emitpcode(POC_MOVWF, pct);
6136                 
6137           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6138 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6139           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6140
6141           /* WREG already holds left + 0x80 */
6142           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6143 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6144         }
6145         
6146         if(ifx)ifx->generated = 1;
6147
6148         if(AOP_SIZE(result)) {
6149           pic16_emitpLabel(tlbl->key);
6150           pic16_emitpLabel(falselbl->key);
6151           pic16_outBitOp( result, pct2 );
6152         } else {
6153           pic16_emitpLabel(tlbl->key);
6154         }
6155
6156       } else {
6157         /* unsigned compare */      
6158         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6159
6160         compareAopfirstpass=1;
6161         while(size--) {
6162           
6163           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6164           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6165
6166         }
6167
6168         if(ifx)ifx->generated = 1;
6169         if(AOP_SIZE(result)) {
6170
6171           pic16_emitpLabel(falselbl->key);
6172           pic16_outBitC( result );
6173         }
6174
6175       }
6176     }
6177 }
6178
6179 #endif  /* } */
6180
6181
6182
6183 /*-----------------------------------------------------------------*/
6184 /* genCmpGt :- greater than comparison                             */
6185 /*-----------------------------------------------------------------*/
6186 static void genCmpGt (iCode *ic, iCode *ifx)
6187 {
6188   operand *left, *right, *result;
6189   sym_link *letype , *retype;
6190   int sign ;
6191
6192     FENTRY;
6193     
6194     left = IC_LEFT(ic);
6195     right= IC_RIGHT(ic);
6196     result = IC_RESULT(ic);
6197
6198     letype = getSpec(operandType(left));
6199     retype =getSpec(operandType(right));
6200     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6201     /* assign the amsops */
6202     pic16_aopOp (left,ic,FALSE);
6203     pic16_aopOp (right,ic,FALSE);
6204     pic16_aopOp (result,ic,TRUE);
6205
6206     genCmp(right, left, result, ifx, sign);
6207
6208     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210     pic16_freeAsmop(result,NULL,ic,TRUE); 
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* genCmpLt - less than comparisons                                */
6215 /*-----------------------------------------------------------------*/
6216 static void genCmpLt (iCode *ic, iCode *ifx)
6217 {
6218   operand *left, *right, *result;
6219   sym_link *letype , *retype;
6220   int sign ;
6221
6222     FENTRY;
6223
6224     left = IC_LEFT(ic);
6225     right= IC_RIGHT(ic);
6226     result = IC_RESULT(ic);
6227
6228     letype = getSpec(operandType(left));
6229     retype =getSpec(operandType(right));
6230     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6231
6232     /* assign the amsops */
6233     pic16_aopOp (left,ic,FALSE);
6234     pic16_aopOp (right,ic,FALSE);
6235     pic16_aopOp (result,ic,TRUE);
6236
6237     genCmp(left, right, result, ifx, sign);
6238
6239     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6240     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6241     pic16_freeAsmop(result,NULL,ic,TRUE); 
6242 }
6243
6244 #if 0
6245 // not needed ATM
6246 // FIXME reenable literal optimisation when the pic16 port is stable
6247
6248 /*-----------------------------------------------------------------*/
6249 /* genc16bit2lit - compare a 16 bit value to a literal             */
6250 /*-----------------------------------------------------------------*/
6251 static void genc16bit2lit(operand *op, int lit, int offset)
6252 {
6253   int i;
6254
6255   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6256   if( (lit&0xff) == 0) 
6257     i=1;
6258   else
6259     i=0;
6260
6261   switch( BYTEofLONG(lit,i)) { 
6262   case 0:
6263     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6264     break;
6265   case 1:
6266     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6267     break;
6268   case 0xff:
6269     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6270     break;
6271   default:
6272     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6273     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6274   }
6275
6276   i ^= 1;
6277
6278   switch( BYTEofLONG(lit,i)) { 
6279   case 0:
6280     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6281     break;
6282   case 1:
6283     emitSKPNZ;
6284     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6285     break;
6286   case 0xff:
6287     emitSKPNZ;
6288     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6289     break;
6290   default:
6291     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6292     emitSKPNZ;
6293     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6294
6295   }
6296
6297 }
6298 #endif
6299
6300 #if 0
6301 // not needed ATM
6302 /*-----------------------------------------------------------------*/
6303 /* gencjneshort - compare and jump if not equal                    */
6304 /*-----------------------------------------------------------------*/
6305 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6306 {
6307   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6308   int offset = 0;
6309   int res_offset = 0;  /* the result may be a different size then left or right */
6310   int res_size = AOP_SIZE(result);
6311   resolvedIfx rIfx;
6312   symbol *lbl, *lbl_done;
6313
6314   unsigned long lit = 0L;
6315   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6316
6317   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6318   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6319   if(result)
6320     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6321   resolveIfx(&rIfx,ifx);
6322   lbl =  newiTempLabel(NULL);
6323   lbl_done =  newiTempLabel(NULL);
6324
6325
6326   /* if the left side is a literal or 
6327      if the right is in a pointer register and left 
6328      is not */
6329   if ((AOP_TYPE(left) == AOP_LIT) || 
6330       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6331     operand *t = right;
6332     right = left;
6333     left = t;
6334   }
6335   if(AOP_TYPE(right) == AOP_LIT)
6336     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6337
6338   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6339     preserve_result = 1;
6340
6341   if(result && !preserve_result)
6342     {
6343       int i;
6344       for(i = 0; i < AOP_SIZE(result); i++)
6345         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6346     }
6347
6348
6349   /* if the right side is a literal then anything goes */
6350   if (AOP_TYPE(right) == AOP_LIT &&
6351       AOP_TYPE(left) != AOP_DIR ) {
6352     switch(size) {
6353     case 2:
6354       genc16bit2lit(left, lit, 0);
6355       emitSKPZ;
6356       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6357       break;
6358     default:
6359       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6360       while (size--) {
6361         if(lit & 0xff) {
6362           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6363           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6364         } else {
6365           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6366         }
6367
6368         emitSKPZ;
6369         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6370         offset++;
6371         if(res_offset < res_size-1)
6372           res_offset++;
6373         lit >>= 8;
6374       }
6375       break;
6376     }
6377   }
6378
6379   /* if the right side is in a register or in direct space or
6380      if the left is a pointer register & right is not */    
6381   else if (AOP_TYPE(right) == AOP_REG ||
6382            AOP_TYPE(right) == AOP_DIR || 
6383            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6384            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6385     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6386     int lbl_key = lbl->key;
6387
6388     if(result) {
6389       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6390       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6391     }else {
6392       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6393       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6394               __FUNCTION__,__LINE__);
6395       return;
6396     }
6397    
6398 /*     switch(size) { */
6399 /*     case 2: */
6400 /*       genc16bit2lit(left, lit, 0); */
6401 /*       emitSKPNZ; */
6402 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6403 /*       break; */
6404 /*     default: */
6405     while (size--) {
6406       int emit_skip=1;
6407       if((AOP_TYPE(left) == AOP_DIR) && 
6408          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6409
6410         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6411         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6412
6413       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6414             
6415         switch (lit & 0xff) {
6416         case 0:
6417           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6418           break;
6419         case 1:
6420           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6421           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6422           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6423           emit_skip=0;
6424           break;
6425         case 0xff:
6426           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6427           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6428           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6429           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6430           emit_skip=0;
6431           break;
6432         default:
6433           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6434           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6435         }
6436         lit >>= 8;
6437
6438       } else {
6439         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6440       }
6441       if(emit_skip) {
6442         if(AOP_TYPE(result) == AOP_CRY) {
6443           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6444           if(rIfx.condition)
6445             emitSKPNZ;
6446           else
6447             emitSKPZ;
6448           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6449         } else {
6450           /* fix me. probably need to check result size too */
6451           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6452           if(rIfx.condition)
6453             emitSKPZ;
6454           else
6455             emitSKPNZ;
6456           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6457           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6458         }
6459         if(ifx)
6460           ifx->generated=1;
6461       }
6462       emit_skip++;
6463       offset++;
6464       if(res_offset < res_size-1)
6465         res_offset++;
6466     }
6467 /*       break; */
6468 /*     } */
6469   } else if(AOP_TYPE(right) == AOP_REG &&
6470             AOP_TYPE(left) != AOP_DIR){
6471
6472     while(size--) {
6473       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6474       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6475       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6476       if(rIfx.condition)
6477         emitSKPNZ;
6478       else
6479         emitSKPZ;
6480       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6481       offset++;
6482       if(res_offset < res_size-1)
6483         res_offset++;
6484     }
6485       
6486   }else{
6487     /* right is a pointer reg need both a & b */
6488     while(size--) {
6489       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6490       if(strcmp(l,"b"))
6491         pic16_emitcode("mov","b,%s",l);
6492       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6493       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6494       offset++;
6495     }
6496   }
6497
6498   if(result && preserve_result)
6499     {
6500       int i;
6501       for(i = 0; i < AOP_SIZE(result); i++)
6502         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6503     }
6504
6505   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6506
6507   if(result && preserve_result)
6508     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6509
6510   if(!rIfx.condition)
6511     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6512
6513   pic16_emitpLabel(lbl->key);
6514
6515   if(result && preserve_result)
6516     {
6517       int i;
6518       for(i = 0; i < AOP_SIZE(result); i++)
6519         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6520
6521       pic16_emitpLabel(lbl_done->key);
6522    }
6523
6524   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6525
6526   if(ifx)
6527     ifx->generated = 1;
6528 }
6529 #endif
6530
6531 #if 0
6532 /*-----------------------------------------------------------------*/
6533 /* gencjne - compare and jump if not equal                         */
6534 /*-----------------------------------------------------------------*/
6535 static void gencjne(operand *left, operand *right, iCode *ifx)
6536 {
6537     symbol *tlbl  = newiTempLabel(NULL);
6538
6539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6540     gencjneshort(left, right, lbl);
6541
6542     pic16_emitcode("mov","a,%s",one);
6543     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6544     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6545     pic16_emitcode("clr","a");
6546     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6547
6548     pic16_emitpLabel(lbl->key);
6549     pic16_emitpLabel(tlbl->key);
6550
6551 }
6552 #endif
6553
6554
6555 /*-----------------------------------------------------------------*/
6556 /* is_LitOp - check if operand has to be treated as literal        */
6557 /*-----------------------------------------------------------------*/
6558 static bool is_LitOp(operand *op)
6559 {
6560   return ((AOP_TYPE(op) == AOP_LIT)
6561       || ( (AOP_TYPE(op) == AOP_PCODE)
6562           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6563               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6564 }
6565
6566 /*-----------------------------------------------------------------*/
6567 /* is_LitAOp - check if operand has to be treated as literal        */
6568 /*-----------------------------------------------------------------*/
6569 static bool is_LitAOp(asmop *aop)
6570 {
6571   return ((aop->type == AOP_LIT)
6572       || ( (aop->type == AOP_PCODE)
6573           && ( (aop->aopu.pcop->type == PO_LITERAL)
6574               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6575 }
6576
6577
6578
6579 /*-----------------------------------------------------------------*/
6580 /* genCmpEq - generates code for equal to                          */
6581 /*-----------------------------------------------------------------*/
6582 static void genCmpEq (iCode *ic, iCode *ifx)
6583 {
6584   operand *left, *right, *result;
6585   symbol *falselbl = newiTempLabel(NULL);
6586   symbol *donelbl = newiTempLabel(NULL);
6587
6588   int preserve_result = 0;
6589   int generate_result = 0;
6590   int i=0;
6591   unsigned long lit = -1;
6592
6593   FENTRY;
6594   
6595   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6596   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6597   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6598  
6599   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6600
6601   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6602     {
6603       werror(W_POSSBUG2, __FILE__, __LINE__);
6604       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6605       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6606       goto release;
6607     }
6608
6609   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6610     {
6611       operand *tmp = right ;
6612       right = left;
6613       left = tmp;
6614     }
6615
6616   if (AOP_TYPE(right) == AOP_LIT) {
6617     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6618   }
6619
6620   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6621     preserve_result = 1;
6622
6623   if(result && AOP_SIZE(result))
6624     generate_result = 1;
6625
6626   if(generate_result && !preserve_result)
6627     {
6628       for(i = 0; i < AOP_SIZE(result); i++)
6629         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6630     }
6631
6632   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6633   for(i=0; i < AOP_SIZE(left); i++)
6634     {
6635       if(AOP_TYPE(left) != AOP_ACC)
6636         {
6637           if(is_LitOp(left))
6638             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6639           else
6640             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6641         }
6642       if(is_LitOp(right)) {
6643         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6644           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6645         }
6646       } else
6647         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6648
6649       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6650     }
6651
6652   // result == true
6653
6654   if(generate_result && preserve_result)
6655     {
6656       for(i = 0; i < AOP_SIZE(result); i++)
6657         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6658     }
6659
6660   if(generate_result)
6661     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6662
6663   if(generate_result && preserve_result)
6664     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6665
6666   if(ifx && IC_TRUE(ifx))
6667     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6668
6669   if(ifx && IC_FALSE(ifx))
6670     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6671
6672   pic16_emitpLabel(falselbl->key);
6673
6674   // result == false
6675
6676   if(ifx && IC_FALSE(ifx))
6677     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6678
6679   if(generate_result && preserve_result)
6680     {
6681       for(i = 0; i < AOP_SIZE(result); i++)
6682         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6683     }
6684
6685   pic16_emitpLabel(donelbl->key);
6686
6687   if(ifx)
6688     ifx->generated = 1;
6689
6690 release:
6691   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6692   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6693   pic16_freeAsmop(result,NULL,ic,TRUE);
6694
6695 }
6696
6697
6698 #if 0
6699 // old version kept for reference
6700
6701 /*-----------------------------------------------------------------*/
6702 /* genCmpEq - generates code for equal to                          */
6703 /*-----------------------------------------------------------------*/
6704 static void genCmpEq (iCode *ic, iCode *ifx)
6705 {
6706     operand *left, *right, *result;
6707     unsigned long lit = 0L;
6708     int size,offset=0;
6709     symbol *falselbl  = newiTempLabel(NULL);
6710
6711
6712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6713
6714     if(ifx)
6715       DEBUGpic16_emitcode ("; ifx is non-null","");
6716     else
6717       DEBUGpic16_emitcode ("; ifx is null","");
6718
6719     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6720     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6721     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6722
6723     size = max(AOP_SIZE(left),AOP_SIZE(right));
6724
6725     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6726
6727     /* if literal, literal on the right or 
6728     if the right is in a pointer register and left 
6729     is not */
6730     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6731         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6732       operand *tmp = right ;
6733       right = left;
6734       left = tmp;
6735     }
6736
6737
6738     if(ifx && !AOP_SIZE(result)){
6739         symbol *tlbl;
6740         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6741         /* if they are both bit variables */
6742         if (AOP_TYPE(left) == AOP_CRY &&
6743             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6744                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6745             if(AOP_TYPE(right) == AOP_LIT){
6746                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6747                 if(lit == 0L){
6748                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6749                     pic16_emitcode("cpl","c");
6750                 } else if(lit == 1L) {
6751                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6752                 } else {
6753                     pic16_emitcode("clr","c");
6754                 }
6755                 /* AOP_TYPE(right) == AOP_CRY */
6756             } else {
6757                 symbol *lbl = newiTempLabel(NULL);
6758                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6759                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6760                 pic16_emitcode("cpl","c");
6761                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6762             }
6763             /* if true label then we jump if condition
6764             supplied is true */
6765             tlbl = newiTempLabel(NULL);
6766             if ( IC_TRUE(ifx) ) {
6767                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6768                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6769             } else {
6770                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6771                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6772             }
6773             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6774
6775                 {
6776                 /* left and right are both bit variables, result is carry */
6777                         resolvedIfx rIfx;
6778               
6779                         resolveIfx(&rIfx,ifx);
6780
6781                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6782                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6783                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6784                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6785                         genSkipz2(&rIfx,0);
6786                 }
6787         } else {
6788
6789                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6790
6791                         /* They're not both bit variables. Is the right a literal? */
6792                         if(AOP_TYPE(right) == AOP_LIT) {
6793                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6794             
6795                         switch(size) {
6796
6797                                 case 1:
6798                                         switch(lit & 0xff) {
6799                                                 case 1:
6800                                                                 if ( IC_TRUE(ifx) ) {
6801                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6802                                                                         emitSKPNZ;
6803                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6804                                                                 } else {
6805                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6806                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6807                                                                 }
6808                                                                 break;
6809                                                 case 0xff:
6810                                                                 if ( IC_TRUE(ifx) ) {
6811                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6812                                                                         emitSKPNZ;
6813                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6814                                                                 } else {
6815                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6816                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6817                                                                 }
6818                                                                 break;
6819                                                 default:
6820                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6821                                                                 if(lit)
6822                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6823                                                                 genSkip(ifx,'z');
6824                                         } // switch lit
6825
6826
6827                                         /* end of size == 1 */
6828                                         break;
6829               
6830                                 case 2:
6831                                         genc16bit2lit(left,lit,offset);
6832                                         genSkip(ifx,'z');
6833                                         break;
6834                                         /* end of size == 2 */
6835
6836                                 default:
6837                                         /* size is 4 */
6838                                         if(lit==0) {
6839                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6840                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6841                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6842                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6843                                                 genSkip(ifx,'z');
6844                                         } else {
6845                                                 /* search for patterns that can be optimized */
6846
6847                                                 genc16bit2lit(left,lit,0);
6848                                                 lit >>= 16;
6849                                                 if(lit) {
6850                                                                 if(IC_TRUE(ifx))
6851                                                                 emitSKPZ; // if hi word unequal
6852                                                                 else
6853                                                                 emitSKPNZ; // if hi word equal
6854                                                                 // fail early
6855                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6856                                                         genc16bit2lit(left,lit,2);
6857                                                         genSkip(ifx,'z');
6858                                                 } else {
6859                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6860                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6861                                                         genSkip(ifx,'z');
6862                                                 }
6863                                         }
6864                                                 pic16_emitpLabel(falselbl->key);
6865                                                 break;
6866
6867                         } // switch size
6868           
6869                         ifx->generated = 1;
6870                         goto release ;
6871             
6872
6873           } else if(AOP_TYPE(right) == AOP_CRY ) {
6874             /* we know the left is not a bit, but that the right is */
6875             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6876             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6877                       pic16_popGet(AOP(right),offset));
6878             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6879
6880             /* if the two are equal, then W will be 0 and the Z bit is set
6881              * we could test Z now, or go ahead and check the high order bytes if
6882              * the variable we're comparing is larger than a byte. */
6883
6884             while(--size)
6885               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6886
6887             if ( IC_TRUE(ifx) ) {
6888               emitSKPNZ;
6889               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6890               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6891             } else {
6892               emitSKPZ;
6893               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6894               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6895             }
6896
6897           } else {
6898             /* They're both variables that are larger than bits */
6899             int s = size;
6900
6901             tlbl = newiTempLabel(NULL);
6902
6903             while(size--) {
6904               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6905               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6906
6907               if ( IC_TRUE(ifx) ) {
6908                 if(size) {
6909                   emitSKPZ;
6910                 
6911                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6912
6913                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6914                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6915                 } else {
6916                   emitSKPNZ;
6917
6918                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6919
6920
6921                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6922                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6923                 }
6924               } else {
6925                 emitSKPZ;
6926
6927                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6928
6929                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6930                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6931               }
6932               offset++;
6933             }
6934             if(s>1 && IC_TRUE(ifx)) {
6935               pic16_emitpLabel(tlbl->key);
6936               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6937             }
6938           }
6939         }
6940         /* mark the icode as generated */
6941         ifx->generated = 1;
6942         goto release ;
6943     }
6944
6945     /* if they are both bit variables */
6946     if (AOP_TYPE(left) == AOP_CRY &&
6947         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6948         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6949         if(AOP_TYPE(right) == AOP_LIT){
6950             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6951             if(lit == 0L){
6952                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6953                 pic16_emitcode("cpl","c");
6954             } else if(lit == 1L) {
6955                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6956             } else {
6957                 pic16_emitcode("clr","c");
6958             }
6959             /* AOP_TYPE(right) == AOP_CRY */
6960         } else {
6961             symbol *lbl = newiTempLabel(NULL);
6962             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6963             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6964             pic16_emitcode("cpl","c");
6965             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6966         }
6967         /* c = 1 if egal */
6968         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6969             pic16_outBitC(result);
6970             goto release ;
6971         }
6972         if (ifx) {
6973             genIfxJump (ifx,"c");
6974             goto release ;
6975         }
6976         /* if the result is used in an arithmetic operation
6977         then put the result in place */
6978         pic16_outBitC(result);
6979     } else {
6980       
6981       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6982       gencjne(left,right,result,ifx);
6983 /*
6984       if(ifx) 
6985         gencjne(left,right,newiTempLabel(NULL));
6986       else {
6987         if(IC_TRUE(ifx)->key)
6988           gencjne(left,right,IC_TRUE(ifx)->key);
6989         else
6990           gencjne(left,right,IC_FALSE(ifx)->key);
6991         ifx->generated = 1;
6992         goto release ;
6993       }
6994       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6995         pic16_aopPut(AOP(result),"a",0);
6996         goto release ;
6997       }
6998
6999       if (ifx) {
7000         genIfxJump (ifx,"a");
7001         goto release ;
7002       }
7003 */
7004       /* if the result is used in an arithmetic operation
7005          then put the result in place */
7006 /*
7007       if (AOP_TYPE(result) != AOP_CRY) 
7008         pic16_outAcc(result);
7009 */
7010       /* leave the result in acc */
7011     }
7012
7013 release:
7014     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7015     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7016     pic16_freeAsmop(result,NULL,ic,TRUE);
7017 }
7018 #endif
7019
7020 /*-----------------------------------------------------------------*/
7021 /* ifxForOp - returns the icode containing the ifx for operand     */
7022 /*-----------------------------------------------------------------*/
7023 static iCode *ifxForOp ( operand *op, iCode *ic )
7024 {
7025   FENTRY2;
7026
7027     /* if true symbol then needs to be assigned */
7028     if (IS_TRUE_SYMOP(op))
7029         return NULL ;
7030
7031     /* if this has register type condition and
7032     the next instruction is ifx with the same operand
7033     and live to of the operand is upto the ifx only then */
7034     if (ic->next
7035         && ic->next->op == IFX
7036         && IC_COND(ic->next)->key == op->key
7037         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7038         ) {
7039                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7040           return ic->next;
7041     }
7042
7043     /*
7044     if (ic->next &&
7045         ic->next->op == IFX &&
7046         IC_COND(ic->next)->key == op->key) {
7047       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7048       return ic->next;
7049     }
7050     */
7051
7052     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7053     if (ic->next &&
7054         ic->next->op == IFX)
7055       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7056
7057     if (ic->next &&
7058         ic->next->op == IFX &&
7059         IC_COND(ic->next)->key == op->key) {
7060       DEBUGpic16_emitcode ("; "," key is okay");
7061       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7062                            OP_SYMBOL(op)->liveTo,
7063                            ic->next->seq);
7064     }
7065
7066 #if 0
7067     /* the code below is completely untested
7068      * it just allows ulong2fs.c compile -- VR */
7069          
7070     ic = ic->next;
7071     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7072                                         __FILE__, __FUNCTION__, __LINE__);
7073         
7074     /* if this has register type condition and
7075     the next instruction is ifx with the same operand
7076     and live to of the operand is upto the ifx only then */
7077     if (ic->next &&
7078         ic->next->op == IFX &&
7079         IC_COND(ic->next)->key == op->key &&
7080         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7081         return ic->next;
7082
7083     if (ic->next &&
7084         ic->next->op == IFX &&
7085         IC_COND(ic->next)->key == op->key) {
7086       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7087       return ic->next;
7088     }
7089
7090     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7091                                         __FILE__, __FUNCTION__, __LINE__);
7092
7093 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7094 #endif
7095
7096     return NULL;
7097 }
7098 /*-----------------------------------------------------------------*/
7099 /* genAndOp - for && operation                                     */
7100 /*-----------------------------------------------------------------*/
7101 static void genAndOp (iCode *ic)
7102 {
7103   operand *left,*right, *result;
7104 /*     symbol *tlbl; */
7105
7106     FENTRY;
7107
7108     /* note here that && operations that are in an
7109     if statement are taken away by backPatchLabels
7110     only those used in arthmetic operations remain */
7111     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7112     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7113     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7114
7115     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7116
7117     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7118     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7119     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7120
7121     /* if both are bit variables */
7122 /*     if (AOP_TYPE(left) == AOP_CRY && */
7123 /*         AOP_TYPE(right) == AOP_CRY ) { */
7124 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7125 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7126 /*         pic16_outBitC(result); */
7127 /*     } else { */
7128 /*         tlbl = newiTempLabel(NULL); */
7129 /*         pic16_toBoolean(left);     */
7130 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7131 /*         pic16_toBoolean(right); */
7132 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7133 /*         pic16_outBitAcc(result); */
7134 /*     } */
7135
7136     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7137     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7138     pic16_freeAsmop(result,NULL,ic,TRUE);
7139 }
7140
7141
7142 /*-----------------------------------------------------------------*/
7143 /* genOrOp - for || operation                                      */
7144 /*-----------------------------------------------------------------*/
7145 /*
7146   tsd pic port -
7147   modified this code, but it doesn't appear to ever get called
7148 */
7149
7150 static void genOrOp (iCode *ic)
7151 {
7152   operand *left,*right, *result;
7153   symbol *tlbl;
7154
7155     FENTRY;  
7156
7157   /* note here that || operations that are in an
7158     if statement are taken away by backPatchLabels
7159     only those used in arthmetic operations remain */
7160     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7161     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7162     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7163
7164     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7165
7166     /* if both are bit variables */
7167     if (AOP_TYPE(left) == AOP_CRY &&
7168         AOP_TYPE(right) == AOP_CRY ) {
7169       pic16_emitcode("clrc","");
7170       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7171                AOP(left)->aopu.aop_dir,
7172                AOP(left)->aopu.aop_dir);
7173       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7174                AOP(right)->aopu.aop_dir,
7175                AOP(right)->aopu.aop_dir);
7176       pic16_emitcode("setc","");
7177
7178     } else {
7179         tlbl = newiTempLabel(NULL);
7180         pic16_toBoolean(left);
7181         emitSKPZ;
7182         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7183         pic16_toBoolean(right);
7184         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7185
7186         pic16_outBitAcc(result);
7187     }
7188
7189     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7190     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7191     pic16_freeAsmop(result,NULL,ic,TRUE);            
7192 }
7193
7194 /*-----------------------------------------------------------------*/
7195 /* isLiteralBit - test if lit == 2^n                               */
7196 /*-----------------------------------------------------------------*/
7197 static int isLiteralBit(unsigned long lit)
7198 {
7199     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7200     0x100L,0x200L,0x400L,0x800L,
7201     0x1000L,0x2000L,0x4000L,0x8000L,
7202     0x10000L,0x20000L,0x40000L,0x80000L,
7203     0x100000L,0x200000L,0x400000L,0x800000L,
7204     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7205     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7206     int idx;
7207     
7208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7209     for(idx = 0; idx < 32; idx++)
7210         if(lit == pw[idx])
7211             return idx+1;
7212     return 0;
7213 }
7214
7215 /*-----------------------------------------------------------------*/
7216 /* continueIfTrue -                                                */
7217 /*-----------------------------------------------------------------*/
7218 static void continueIfTrue (iCode *ic)
7219 {
7220   FENTRY;
7221   if(IC_TRUE(ic))
7222     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7223   ic->generated = 1;
7224 }
7225
7226 /*-----------------------------------------------------------------*/
7227 /* jmpIfTrue -                                                     */
7228 /*-----------------------------------------------------------------*/
7229 static void jumpIfTrue (iCode *ic)
7230 {
7231   FENTRY;
7232   if(!IC_TRUE(ic))
7233     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7234   ic->generated = 1;
7235 }
7236
7237 /*-----------------------------------------------------------------*/
7238 /* jmpTrueOrFalse -                                                */
7239 /*-----------------------------------------------------------------*/
7240 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7241 {
7242   // ugly but optimized by peephole
7243   FENTRY;
7244   if(IC_TRUE(ic)){
7245     symbol *nlbl = newiTempLabel(NULL);
7246       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7247       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7248       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7249       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7250   } else {
7251     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7252     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7253   }
7254   ic->generated = 1;
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genAnd  - code for and                                          */
7259 /*-----------------------------------------------------------------*/
7260 static void genAnd (iCode *ic, iCode *ifx)
7261 {
7262   operand *left, *right, *result;
7263   int size, offset=0;  
7264   unsigned long lit = 0L;
7265   int bytelit = 0;
7266   resolvedIfx rIfx;
7267
7268     FENTRY;
7269     
7270   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7271   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7272   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7273
7274   resolveIfx(&rIfx,ifx);
7275
7276   /* if left is a literal & right is not then exchange them */
7277   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7278       AOP_NEEDSACC(left)) {
7279     operand *tmp = right ;
7280     right = left;
7281     left = tmp;
7282   }
7283
7284   /* if result = right then exchange them */
7285   if(pic16_sameRegs(AOP(result),AOP(right))){
7286     operand *tmp = right ;
7287     right = left;
7288     left = tmp;
7289   }
7290
7291   /* if right is bit then exchange them */
7292   if (AOP_TYPE(right) == AOP_CRY &&
7293       AOP_TYPE(left) != AOP_CRY){
7294     operand *tmp = right ;
7295     right = left;
7296     left = tmp;
7297   }
7298   if(AOP_TYPE(right) == AOP_LIT)
7299     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7300
7301   size = AOP_SIZE(result);
7302
7303   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7304
7305   // if(bit & yy)
7306   // result = bit & yy;
7307   if (AOP_TYPE(left) == AOP_CRY){
7308     // c = bit & literal;
7309     if(AOP_TYPE(right) == AOP_LIT){
7310       if(lit & 1) {
7311         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7312           // no change
7313           goto release;
7314         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7315       } else {
7316         // bit(result) = 0;
7317         if(size && (AOP_TYPE(result) == AOP_CRY)){
7318           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7319           goto release;
7320         }
7321         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7322           jumpIfTrue(ifx);
7323           goto release;
7324         }
7325         pic16_emitcode("clr","c");
7326       }
7327     } else {
7328       if (AOP_TYPE(right) == AOP_CRY){
7329         // c = bit & bit;
7330         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7331         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7332       } else {
7333         // c = bit & val;
7334         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7335         // c = lsb
7336         pic16_emitcode("rrc","a");
7337         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7338       }
7339     }
7340     // bit = c
7341     // val = c
7342     if(size)
7343       pic16_outBitC(result);
7344     // if(bit & ...)
7345     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7346       genIfxJump(ifx, "c");           
7347     goto release ;
7348   }
7349
7350   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7351   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7352   if((AOP_TYPE(right) == AOP_LIT) &&
7353      (AOP_TYPE(result) == AOP_CRY) &&
7354      (AOP_TYPE(left) != AOP_CRY)){
7355     int posbit = isLiteralBit(lit);
7356     /* left &  2^n */
7357     if(posbit){
7358       posbit--;
7359       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7360       // bit = left & 2^n
7361       if(size)
7362         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7363       // if(left &  2^n)
7364       else{
7365         if(ifx){
7366 /*
7367           if(IC_TRUE(ifx)) {
7368             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7369             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7370           } else {
7371             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7372             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7373           }
7374 */
7375         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7376         size = AOP_SIZE(left);
7377
7378         {
7379           int bp = posbit, ofs=0;
7380           
7381             while(bp > 7) {
7382               bp -= 8;
7383               ofs++;
7384             }
7385
7386           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7387                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7388
7389         }
7390 /*
7391           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7392                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7393 */
7394           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7395           
7396           ifx->generated = 1;
7397         }
7398         goto release;
7399       }
7400     } else {
7401       symbol *tlbl = newiTempLabel(NULL);
7402       int sizel = AOP_SIZE(left);
7403
7404       if(size)
7405         emitSETC;
7406
7407       while(sizel--) {
7408         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7409
7410           /* patch provided by Aaron Colwell */
7411           if((posbit = isLiteralBit(bytelit)) != 0) {
7412               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7413                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7414                                                 (posbit-1),0, PO_GPR_REGISTER));
7415
7416               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7417 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7418           } else {
7419               if (bytelit == 0xff) {
7420                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7421                    * a peephole could optimize it out -- VR */
7422                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7423               } else {
7424                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7425                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7426               }
7427
7428               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7429                             pic16_popGetLabel(tlbl->key));
7430           }
7431         
7432 #if 0
7433           /* old code, left here for reference -- VR 09/2004 */
7434           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7435           // byte ==  2^n ?
7436           if((posbit = isLiteralBit(bytelit)) != 0)
7437             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7438           else{
7439             if(bytelit != 0x0FFL)
7440               pic16_emitcode("anl","a,%s",
7441                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7442             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7443           }
7444 #endif
7445         }
7446         offset++;
7447       }
7448       // bit = left & literal
7449       if(size) {
7450         emitCLRC;
7451         pic16_emitpLabel(tlbl->key);
7452       }
7453       // if(left & literal)
7454       else {
7455         if(ifx) {
7456           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7457           ifx->generated = 1;
7458         }
7459         pic16_emitpLabel(tlbl->key);
7460         goto release;
7461       }
7462     }
7463
7464     pic16_outBitC(result);
7465     goto release ;
7466   }
7467
7468   /* if left is same as result */
7469   if(pic16_sameRegs(AOP(result),AOP(left))){
7470     int know_W = -1;
7471     for(;size--; offset++,lit>>=8) {
7472       if(AOP_TYPE(right) == AOP_LIT){
7473         switch(lit & 0xff) {
7474         case 0x00:
7475           /*  and'ing with 0 has clears the result */
7476 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7477           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7478           break;
7479         case 0xff:
7480           /* and'ing with 0xff is a nop when the result and left are the same */
7481           break;
7482
7483         default:
7484           {
7485             int p = pic16_my_powof2( (~lit) & 0xff );
7486             if(p>=0) {
7487               /* only one bit is set in the literal, so use a bcf instruction */
7488 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7489               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7490
7491             } else {
7492               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7493               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7494               if(know_W != (lit&0xff))
7495                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7496               know_W = lit &0xff;
7497               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7498             }
7499           }    
7500         }
7501       } else {
7502         if (AOP_TYPE(left) == AOP_ACC) {
7503           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7504         } else {                    
7505           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7506           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7507
7508         }
7509       }
7510     }
7511
7512   } else {
7513     // left & result in different registers
7514     if(AOP_TYPE(result) == AOP_CRY){
7515       // result = bit
7516       // if(size), result in bit
7517       // if(!size && ifx), conditional oper: if(left & right)
7518       symbol *tlbl = newiTempLabel(NULL);
7519       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7520       if(size)
7521         pic16_emitcode("setb","c");
7522       while(sizer--){
7523         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7524         pic16_emitcode("anl","a,%s",
7525                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7526         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7527         offset++;
7528       }
7529       if(size){
7530         CLRC;
7531         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7532         pic16_outBitC(result);
7533       } else if(ifx)
7534         jmpTrueOrFalse(ifx, tlbl);
7535     } else {
7536       for(;(size--);offset++) {
7537         // normal case
7538         // result = left & right
7539         if(AOP_TYPE(right) == AOP_LIT){
7540           int t = (lit >> (offset*8)) & 0x0FFL;
7541           switch(t) { 
7542           case 0x00:
7543             pic16_emitcode("clrf","%s",
7544                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7545             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7546             break;
7547           case 0xff:
7548             pic16_emitcode("movf","%s,w",
7549                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7550             pic16_emitcode("movwf","%s",
7551                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7552             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7553             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7554             break;
7555           default:
7556             pic16_emitcode("movlw","0x%x",t);
7557             pic16_emitcode("andwf","%s,w",
7558                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7559             pic16_emitcode("movwf","%s",
7560                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7561               
7562             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7563             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7564             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7565           }
7566           continue;
7567         }
7568
7569         if (AOP_TYPE(left) == AOP_ACC) {
7570           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7571           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7572         } else {
7573           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7574           pic16_emitcode("andwf","%s,w",
7575                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7576           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7577           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7578         }
7579         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7580         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7581       }
7582     }
7583   }
7584
7585   release :
7586     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7587   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7588   pic16_freeAsmop(result,NULL,ic,TRUE);     
7589 }
7590
7591 /*-----------------------------------------------------------------*/
7592 /* genOr  - code for or                                            */
7593 /*-----------------------------------------------------------------*/
7594 static void genOr (iCode *ic, iCode *ifx)
7595 {
7596     operand *left, *right, *result;
7597     int size, offset=0;
7598     unsigned long lit = 0L;
7599
7600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7601
7602     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7603     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7604     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7605
7606     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7607
7608     /* if left is a literal & right is not then exchange them */
7609     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7610         AOP_NEEDSACC(left)) {
7611         operand *tmp = right ;
7612         right = left;
7613         left = tmp;
7614     }
7615
7616     /* if result = right then exchange them */
7617     if(pic16_sameRegs(AOP(result),AOP(right))){
7618         operand *tmp = right ;
7619         right = left;
7620         left = tmp;
7621     }
7622
7623     /* if right is bit then exchange them */
7624     if (AOP_TYPE(right) == AOP_CRY &&
7625         AOP_TYPE(left) != AOP_CRY){
7626         operand *tmp = right ;
7627         right = left;
7628         left = tmp;
7629     }
7630
7631     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7632
7633     if(AOP_TYPE(right) == AOP_LIT)
7634         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7635
7636     size = AOP_SIZE(result);
7637
7638     // if(bit | yy)
7639     // xx = bit | yy;
7640     if (AOP_TYPE(left) == AOP_CRY){
7641         if(AOP_TYPE(right) == AOP_LIT){
7642             // c = bit & literal;
7643             if(lit){
7644                 // lit != 0 => result = 1
7645                 if(AOP_TYPE(result) == AOP_CRY){
7646                   if(size)
7647                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7648                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7649                   //     AOP(result)->aopu.aop_dir,
7650                   //     AOP(result)->aopu.aop_dir);
7651                     else if(ifx)
7652                         continueIfTrue(ifx);
7653                     goto release;
7654                 }
7655             } else {
7656                 // lit == 0 => result = left
7657                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7658                     goto release;
7659                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7660             }
7661         } else {
7662             if (AOP_TYPE(right) == AOP_CRY){
7663               if(pic16_sameRegs(AOP(result),AOP(left))){
7664                 // c = bit | bit;
7665                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7666                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7667                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7668
7669                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7670                          AOP(result)->aopu.aop_dir,
7671                          AOP(result)->aopu.aop_dir);
7672                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7673                          AOP(right)->aopu.aop_dir,
7674                          AOP(right)->aopu.aop_dir);
7675                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7676                          AOP(result)->aopu.aop_dir,
7677                          AOP(result)->aopu.aop_dir);
7678               } else {
7679                 if( AOP_TYPE(result) == AOP_ACC) {
7680                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7681                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7682                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7683                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7684
7685                 } else {
7686
7687                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7688                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7689                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7690                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7691
7692                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7693                                  AOP(result)->aopu.aop_dir,
7694                                  AOP(result)->aopu.aop_dir);
7695                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7696                                  AOP(right)->aopu.aop_dir,
7697                                  AOP(right)->aopu.aop_dir);
7698                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7699                                  AOP(left)->aopu.aop_dir,
7700                                  AOP(left)->aopu.aop_dir);
7701                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7702                                  AOP(result)->aopu.aop_dir,
7703                                  AOP(result)->aopu.aop_dir);
7704                 }
7705               }
7706             } else {
7707                 // c = bit | val;
7708                 symbol *tlbl = newiTempLabel(NULL);
7709                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7710
7711
7712                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7713                 if( AOP_TYPE(right) == AOP_ACC) {
7714                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7715                   emitSKPNZ;
7716                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7717                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7718                 }
7719
7720
7721
7722                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7723                     pic16_emitcode(";XXX setb","c");
7724                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7725                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7726                 pic16_toBoolean(right);
7727                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7728                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7729                     jmpTrueOrFalse(ifx, tlbl);
7730                     goto release;
7731                 } else {
7732                     CLRC;
7733                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7734                 }
7735             }
7736         }
7737         // bit = c
7738         // val = c
7739         if(size)
7740             pic16_outBitC(result);
7741         // if(bit | ...)
7742         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7743             genIfxJump(ifx, "c");           
7744         goto release ;
7745     }
7746
7747     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7748     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7749     if((AOP_TYPE(right) == AOP_LIT) &&
7750        (AOP_TYPE(result) == AOP_CRY) &&
7751        (AOP_TYPE(left) != AOP_CRY)){
7752         if(lit){
7753           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7754             // result = 1
7755             if(size)
7756                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7757             else 
7758                 continueIfTrue(ifx);
7759             goto release;
7760         } else {
7761           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7762             // lit = 0, result = boolean(left)
7763             if(size)
7764                 pic16_emitcode(";XXX setb","c");
7765             pic16_toBoolean(right);
7766             if(size){
7767                 symbol *tlbl = newiTempLabel(NULL);
7768                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7769                 CLRC;
7770                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7771             } else {
7772                 genIfxJump (ifx,"a");
7773                 goto release;
7774             }
7775         }
7776         pic16_outBitC(result);
7777         goto release ;
7778     }
7779
7780     /* if left is same as result */
7781     if(pic16_sameRegs(AOP(result),AOP(left))){
7782       int know_W = -1;
7783       for(;size--; offset++,lit>>=8) {
7784         if(AOP_TYPE(right) == AOP_LIT){
7785           if((lit & 0xff) == 0)
7786             /*  or'ing with 0 has no effect */
7787             continue;
7788           else {
7789             int p = pic16_my_powof2(lit & 0xff);
7790             if(p>=0) {
7791               /* only one bit is set in the literal, so use a bsf instruction */
7792               pic16_emitpcode(POC_BSF,
7793                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7794             } else {
7795               if(know_W != (lit & 0xff))
7796                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7797               know_W = lit & 0xff;
7798               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7799             }
7800                     
7801           }
7802         } else {
7803           if (AOP_TYPE(left) == AOP_ACC) {
7804             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7805             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7806           } else {                  
7807             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7808             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7809
7810             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7811             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7812
7813           }
7814         }
7815       }
7816     } else {
7817         // left & result in different registers
7818         if(AOP_TYPE(result) == AOP_CRY){
7819             // result = bit
7820             // if(size), result in bit
7821             // if(!size && ifx), conditional oper: if(left | right)
7822             symbol *tlbl = newiTempLabel(NULL);
7823             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7824             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7825
7826
7827             if(size)
7828                 pic16_emitcode(";XXX setb","c");
7829             while(sizer--){
7830                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7831                 pic16_emitcode(";XXX orl","a,%s",
7832                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7833                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7834                 offset++;
7835             }
7836             if(size){
7837                 CLRC;
7838                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7839                 pic16_outBitC(result);
7840             } else if(ifx)
7841                 jmpTrueOrFalse(ifx, tlbl);
7842         } else for(;(size--);offset++){
7843           // normal case
7844           // result = left & right
7845           if(AOP_TYPE(right) == AOP_LIT){
7846             int t = (lit >> (offset*8)) & 0x0FFL;
7847             switch(t) { 
7848             case 0x00:
7849               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7850               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7851
7852               pic16_emitcode("movf","%s,w",
7853                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7854               pic16_emitcode("movwf","%s",
7855                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7856               break;
7857             default:
7858               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7859               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7860               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7861
7862               pic16_emitcode("movlw","0x%x",t);
7863               pic16_emitcode("iorwf","%s,w",
7864                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865               pic16_emitcode("movwf","%s",
7866                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7867               
7868             }
7869             continue;
7870           }
7871
7872           // faster than result <- left, anl result,right
7873           // and better if result is SFR
7874           if (AOP_TYPE(left) == AOP_ACC) {
7875             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7876             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7877           } else {
7878             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7879             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7880
7881             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7882             pic16_emitcode("iorwf","%s,w",
7883                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7884           }
7885           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7886           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7887         }
7888     }
7889
7890 release :
7891     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7892     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7893     pic16_freeAsmop(result,NULL,ic,TRUE);     
7894 }
7895
7896 /*-----------------------------------------------------------------*/
7897 /* genXor - code for xclusive or                                   */
7898 /*-----------------------------------------------------------------*/
7899 static void genXor (iCode *ic, iCode *ifx)
7900 {
7901   operand *left, *right, *result;
7902   int size, offset=0;
7903   unsigned long lit = 0L;
7904
7905   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7906
7907   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7908   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7909   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7910
7911   /* if left is a literal & right is not ||
7912      if left needs acc & right does not */
7913   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7914       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7915     operand *tmp = right ;
7916     right = left;
7917     left = tmp;
7918   }
7919
7920   /* if result = right then exchange them */
7921   if(pic16_sameRegs(AOP(result),AOP(right))){
7922     operand *tmp = right ;
7923     right = left;
7924     left = tmp;
7925   }
7926
7927   /* if right is bit then exchange them */
7928   if (AOP_TYPE(right) == AOP_CRY &&
7929       AOP_TYPE(left) != AOP_CRY){
7930     operand *tmp = right ;
7931     right = left;
7932     left = tmp;
7933   }
7934   if(AOP_TYPE(right) == AOP_LIT)
7935     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7936
7937   size = AOP_SIZE(result);
7938
7939   // if(bit ^ yy)
7940   // xx = bit ^ yy;
7941   if (AOP_TYPE(left) == AOP_CRY){
7942     if(AOP_TYPE(right) == AOP_LIT){
7943       // c = bit & literal;
7944       if(lit>>1){
7945         // lit>>1  != 0 => result = 1
7946         if(AOP_TYPE(result) == AOP_CRY){
7947           if(size)
7948             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7949             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7950           else if(ifx)
7951             continueIfTrue(ifx);
7952           goto release;
7953         }
7954         pic16_emitcode("setb","c");
7955       } else{
7956         // lit == (0 or 1)
7957         if(lit == 0){
7958           // lit == 0, result = left
7959           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7960             goto release;
7961           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7962         } else{
7963           // lit == 1, result = not(left)
7964           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7965             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7966             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7967             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7968             goto release;
7969           } else {
7970             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7971             pic16_emitcode("cpl","c");
7972           }
7973         }
7974       }
7975
7976     } else {
7977       // right != literal
7978       symbol *tlbl = newiTempLabel(NULL);
7979       if (AOP_TYPE(right) == AOP_CRY){
7980         // c = bit ^ bit;
7981         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7982       }
7983       else{
7984         int sizer = AOP_SIZE(right);
7985         // c = bit ^ val
7986         // if val>>1 != 0, result = 1
7987         pic16_emitcode("setb","c");
7988         while(sizer){
7989           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7990           if(sizer == 1)
7991             // test the msb of the lsb
7992             pic16_emitcode("anl","a,#0xfe");
7993           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7994           sizer--;
7995         }
7996         // val = (0,1)
7997         pic16_emitcode("rrc","a");
7998       }
7999       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8000       pic16_emitcode("cpl","c");
8001       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8002     }
8003     // bit = c
8004     // val = c
8005     if(size)
8006       pic16_outBitC(result);
8007     // if(bit | ...)
8008     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8009       genIfxJump(ifx, "c");           
8010     goto release ;
8011   }
8012
8013   if(pic16_sameRegs(AOP(result),AOP(left))){
8014     /* if left is same as result */
8015     for(;size--; offset++) {
8016       if(AOP_TYPE(right) == AOP_LIT){
8017         int t  = (lit >> (offset*8)) & 0x0FFL;
8018         if(t == 0x00L)
8019           continue;
8020         else
8021           if (IS_AOP_PREG(left)) {
8022             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8023             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8024             pic16_aopPut(AOP(result),"a",offset);
8025           } else {
8026             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8027             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8028             pic16_emitcode("xrl","%s,%s",
8029                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8030                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8031           }
8032       } else {
8033         if (AOP_TYPE(left) == AOP_ACC)
8034           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8035         else {
8036           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8037           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8038 /*
8039           if (IS_AOP_PREG(left)) {
8040             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8041             pic16_aopPut(AOP(result),"a",offset);
8042           } else
8043             pic16_emitcode("xrl","%s,a",
8044                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8045 */
8046         }
8047       }
8048     }
8049   } else {
8050     // left & result in different registers
8051     if(AOP_TYPE(result) == AOP_CRY){
8052       // result = bit
8053       // if(size), result in bit
8054       // if(!size && ifx), conditional oper: if(left ^ right)
8055       symbol *tlbl = newiTempLabel(NULL);
8056       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8057       if(size)
8058         pic16_emitcode("setb","c");
8059       while(sizer--){
8060         if((AOP_TYPE(right) == AOP_LIT) &&
8061            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8062           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8063         } else {
8064           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8065           pic16_emitcode("xrl","a,%s",
8066                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8067         }
8068         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8069         offset++;
8070       }
8071       if(size){
8072         CLRC;
8073         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8074         pic16_outBitC(result);
8075       } else if(ifx)
8076         jmpTrueOrFalse(ifx, tlbl);
8077     } else for(;(size--);offset++){
8078       // normal case
8079       // result = left & right
8080       if(AOP_TYPE(right) == AOP_LIT){
8081         int t = (lit >> (offset*8)) & 0x0FFL;
8082         switch(t) { 
8083         case 0x00:
8084           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8085           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8086           pic16_emitcode("movf","%s,w",
8087                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8088           pic16_emitcode("movwf","%s",
8089                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8090           break;
8091         case 0xff:
8092           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8093           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8094           pic16_emitcode("comf","%s,w",
8095                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8096           pic16_emitcode("movwf","%s",
8097                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8098           break;
8099         default:
8100           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8101           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8102           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8103           pic16_emitcode("movlw","0x%x",t);
8104           pic16_emitcode("xorwf","%s,w",
8105                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8106           pic16_emitcode("movwf","%s",
8107                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8108
8109         }
8110         continue;
8111       }
8112
8113       // faster than result <- left, anl result,right
8114       // and better if result is SFR
8115       if (AOP_TYPE(left) == AOP_ACC) {
8116         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8117         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118       } else {
8119         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8121         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8123       }
8124       if ( AOP_TYPE(result) != AOP_ACC){
8125         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8126         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8127       }
8128     }
8129   }
8130
8131   release :
8132     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8133   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8134   pic16_freeAsmop(result,NULL,ic,TRUE);     
8135 }
8136
8137 /*-----------------------------------------------------------------*/
8138 /* genInline - write the inline code out                           */
8139 /*-----------------------------------------------------------------*/
8140 static void genInline (iCode *ic)
8141 {
8142   char *buffer, *bp, *bp1;
8143     
8144         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8145
8146         _G.inLine += (!options.asmpeep);
8147
8148         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8149         strcpy(buffer,IC_INLINE(ic));
8150         
8151         while((bp1=strstr(bp, "\\n"))) {
8152           *bp1++ = '\n';
8153           *bp1++ = ' ';
8154           bp = bp1;
8155         }
8156         bp = bp1 = buffer;
8157
8158 #if 0
8159   /* This is an experimental code for #pragma inline
8160      and is temporarily disabled for 2.5.0 release */
8161         if(asmInlineMap)
8162         {
8163           symbol *sym;
8164           char *s;
8165           char *cbuf;
8166           int cblen;
8167
8168             cbuf = Safe_strdup(buffer);
8169             cblen = strlen(buffer)+1;
8170             memset(cbuf, 0, cblen);
8171
8172             bp = buffer;
8173             bp1 = cbuf;
8174             while(*bp) {
8175               if(*bp != '%')*bp1++ = *bp++;
8176               else {
8177                 int i;
8178
8179                   bp++;
8180                   i = *bp - '0';
8181                   if(i>elementsInSet(asmInlineMap))break;
8182                   
8183                   bp++;
8184                   s = indexSet(asmInlineMap, i);
8185                   DEBUGpc("searching symbol s = `%s'", s);
8186                   sym = findSym(SymbolTab, NULL, s);
8187
8188                   if(sym->reqv) {
8189                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8190                   } else {
8191                     strcat(bp1, sym->rname);
8192                   }
8193                   
8194                   while(*bp1)bp1++;
8195               }
8196               
8197               if(strlen(bp1) > cblen - 16) {
8198                 int i = strlen(cbuf);
8199                 cblen += 50;
8200                 cbuf = realloc(cbuf, cblen);
8201                 memset(cbuf+i, 0, 50);
8202                 bp1 = cbuf + i;
8203               }
8204             }
8205             
8206             free(buffer);
8207             buffer = Safe_strdup( cbuf );
8208             free(cbuf);
8209             
8210             bp = bp1 = buffer;
8211         }
8212 #endif  /* 0 */
8213
8214         /* emit each line as a code */
8215         while (*bp) {
8216                 if (*bp == '\n') {
8217                         *bp++ = '\0';
8218
8219                         if(*bp1)
8220                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8221                         bp1 = bp;
8222                 } else {
8223                         if (*bp == ':') {
8224                                 bp++;
8225                                 *bp = '\0';
8226                                 bp++;
8227
8228                                 /* print label, use this special format with NULL directive
8229                                  * to denote that the argument should not be indented with tab */
8230                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8231                                 bp1 = bp;
8232                         } if (*bp == ';') {
8233                                 /* advance to end of line (prevent splitting of comments at ':' */
8234                                 while (*bp && *bp != '\n') {
8235                                         bp++;
8236                                 } // while
8237                         } else
8238                                 bp++;
8239                 }
8240         }
8241
8242         if ((bp1 != bp) && *bp1)
8243                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8244
8245
8246     Safe_free(buffer);
8247
8248     _G.inLine -= (!options.asmpeep);
8249 }
8250
8251 /*-----------------------------------------------------------------*/
8252 /* genRRC - rotate right with carry                                */
8253 /*-----------------------------------------------------------------*/
8254 static void genRRC (iCode *ic)
8255 {
8256   operand *left , *result ;
8257   int size, offset = 0, same;
8258
8259   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8260
8261   /* rotate right with carry */
8262   left = IC_LEFT(ic);
8263   result=IC_RESULT(ic);
8264   pic16_aopOp (left,ic,FALSE);
8265   pic16_aopOp (result,ic,TRUE);
8266
8267   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8268
8269   same = pic16_sameRegs(AOP(result),AOP(left));
8270
8271   size = AOP_SIZE(result);    
8272
8273   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8274
8275   /* get the lsb and put it into the carry */
8276   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8277
8278   offset = 0 ;
8279
8280   while(size--) {
8281
8282     if(same) {
8283       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8284     } else {
8285       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8286       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8287     }
8288
8289     offset++;
8290   }
8291
8292   pic16_freeAsmop(left,NULL,ic,TRUE);
8293   pic16_freeAsmop(result,NULL,ic,TRUE);
8294 }
8295
8296 /*-----------------------------------------------------------------*/
8297 /* genRLC - generate code for rotate left with carry               */
8298 /*-----------------------------------------------------------------*/
8299 static void genRLC (iCode *ic)
8300 {    
8301   operand *left , *result ;
8302   int size, offset = 0;
8303   int same;
8304
8305   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8306   /* rotate right with carry */
8307   left = IC_LEFT(ic);
8308   result=IC_RESULT(ic);
8309   pic16_aopOp (left,ic,FALSE);
8310   pic16_aopOp (result,ic,TRUE);
8311
8312   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8313
8314   same = pic16_sameRegs(AOP(result),AOP(left));
8315
8316   /* move it to the result */
8317   size = AOP_SIZE(result);    
8318
8319   /* get the msb and put it into the carry */
8320   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8321
8322   offset = 0 ;
8323
8324   while(size--) {
8325
8326     if(same) {
8327       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8328     } else {
8329       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8330       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8331     }
8332
8333     offset++;
8334   }
8335
8336
8337   pic16_freeAsmop(left,NULL,ic,TRUE);
8338   pic16_freeAsmop(result,NULL,ic,TRUE);
8339 }
8340
8341
8342 /* gpasm can get the highest order bit with HIGH/UPPER
8343  * so the following probably is not needed -- VR */
8344  
8345 /*-----------------------------------------------------------------*/
8346 /* genGetHbit - generates code get highest order bit               */
8347 /*-----------------------------------------------------------------*/
8348 static void genGetHbit (iCode *ic)
8349 {
8350     operand *left, *result;
8351     left = IC_LEFT(ic);
8352     result=IC_RESULT(ic);
8353     pic16_aopOp (left,ic,FALSE);
8354     pic16_aopOp (result,ic,FALSE);
8355
8356     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8357     /* get the highest order byte into a */
8358     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8359     if(AOP_TYPE(result) == AOP_CRY){
8360         pic16_emitcode("rlc","a");
8361         pic16_outBitC(result);
8362     }
8363     else{
8364         pic16_emitcode("rl","a");
8365         pic16_emitcode("anl","a,#0x01");
8366         pic16_outAcc(result);
8367     }
8368
8369
8370     pic16_freeAsmop(left,NULL,ic,TRUE);
8371     pic16_freeAsmop(result,NULL,ic,TRUE);
8372 }
8373
8374 #if 0
8375 /*-----------------------------------------------------------------*/
8376 /* AccRol - rotate left accumulator by known count                 */
8377 /*-----------------------------------------------------------------*/
8378 static void AccRol (int shCount)
8379 {
8380     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8381     shCount &= 0x0007;              // shCount : 0..7
8382     switch(shCount){
8383         case 0 :
8384             break;
8385         case 1 :
8386             pic16_emitcode("rl","a");
8387             break;
8388         case 2 :
8389             pic16_emitcode("rl","a");
8390             pic16_emitcode("rl","a");
8391             break;
8392         case 3 :
8393             pic16_emitcode("swap","a");
8394             pic16_emitcode("rr","a");
8395             break;
8396         case 4 :
8397             pic16_emitcode("swap","a");
8398             break;
8399         case 5 :
8400             pic16_emitcode("swap","a");
8401             pic16_emitcode("rl","a");
8402             break;
8403         case 6 :
8404             pic16_emitcode("rr","a");
8405             pic16_emitcode("rr","a");
8406             break;
8407         case 7 :
8408             pic16_emitcode("rr","a");
8409             break;
8410     }
8411 }
8412 #endif
8413
8414 /*-----------------------------------------------------------------*/
8415 /* AccLsh - left shift accumulator by known count                  */
8416 /*-----------------------------------------------------------------*/
8417 static void AccLsh (int shCount)
8418 {
8419         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8420         switch(shCount){
8421                 case 0 :
8422                         return;
8423                         break;
8424                 case 1 :
8425                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8426                         break;
8427                 case 2 :
8428                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8429                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430                         break;
8431                 case 3 :
8432                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8433                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8434                         break;
8435                 case 4 :
8436                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8437                         break;
8438                 case 5 :
8439                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8440                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441                         break;
8442                 case 6 :
8443                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         break;
8446                 case 7 :
8447                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448                         break;
8449         }
8450
8451         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8452 }
8453
8454 /*-----------------------------------------------------------------*/
8455 /* AccRsh - right shift accumulator by known count                 */
8456 /*-----------------------------------------------------------------*/
8457 static void AccRsh (int shCount, int andmask)
8458 {
8459         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8460         switch(shCount){
8461                 case 0 :
8462                         return; break;
8463                 case 1 :
8464                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8465                         break;
8466                 case 2 :
8467                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8468                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469                         break;
8470                 case 3 :
8471                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8472                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8473                         break;
8474                 case 4 :
8475                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8476                         break;
8477                 case 5 :
8478                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8479                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480                         break;
8481                 case 6 :
8482                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8484                         break;
8485                 case 7 :
8486                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487                         break;
8488         }
8489         
8490         if(andmask)
8491                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8492         else
8493                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8494 }
8495
8496 #if 0
8497 /*-----------------------------------------------------------------*/
8498 /* AccSRsh - signed right shift accumulator by known count                 */
8499 /*-----------------------------------------------------------------*/
8500 static void AccSRsh (int shCount)
8501 {
8502     symbol *tlbl ;
8503     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8504     if(shCount != 0){
8505         if(shCount == 1){
8506             pic16_emitcode("mov","c,acc.7");
8507             pic16_emitcode("rrc","a");
8508         } else if(shCount == 2){
8509             pic16_emitcode("mov","c,acc.7");
8510             pic16_emitcode("rrc","a");
8511             pic16_emitcode("mov","c,acc.7");
8512             pic16_emitcode("rrc","a");
8513         } else {
8514             tlbl = newiTempLabel(NULL);
8515             /* rotate right accumulator */
8516             AccRol(8 - shCount);
8517             /* and kill the higher order bits */
8518             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8519             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8520             pic16_emitcode("orl","a,#0x%02x",
8521                      (unsigned char)~SRMask[shCount]);
8522             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8523         }
8524     }
8525 }
8526 #endif
8527
8528 /*-----------------------------------------------------------------*/
8529 /* shiftR1Left2Result - shift right one byte from left to result   */
8530 /*-----------------------------------------------------------------*/
8531 static void shiftR1Left2ResultSigned (operand *left, int offl,
8532                                 operand *result, int offr,
8533                                 int shCount)
8534 {
8535   int same;
8536
8537   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8538
8539   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8540
8541   switch(shCount) {
8542   case 1:
8543     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8544     if(same) 
8545       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8546     else {
8547       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8548       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8549     }
8550
8551     break;
8552   case 2:
8553
8554     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8555     if(same) 
8556       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8557     else {
8558       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8559       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8560     }
8561     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8562     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8563
8564     break;
8565
8566   case 3:
8567     if(same)
8568       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8569     else {
8570       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8571       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8572     }
8573
8574     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8575     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8576     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8577
8578     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8579     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8580
8581     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8582     break;
8583
8584   case 4:
8585     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8586     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8587     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8588     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8589     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8590     break;
8591   case 5:
8592     if(same) {
8593       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8594     } else {
8595       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8596       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8597     }
8598     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8599     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8600     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8601     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8602     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8603     break;
8604
8605   case 6:
8606     if(same) {
8607       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8608       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8609       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8610       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8611       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8612       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8613     } else {
8614       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8615       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8616       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8617       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8618       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8619     }
8620     break;
8621
8622   case 7:
8623     if(same) {
8624       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8625       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8626       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8627       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8628     } else {
8629       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8630       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8631       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8632     }
8633
8634   default:
8635     break;
8636   }
8637 }
8638
8639 /*-----------------------------------------------------------------*/
8640 /* shiftR1Left2Result - shift right one byte from left to result   */
8641 /*-----------------------------------------------------------------*/
8642 static void shiftR1Left2Result (operand *left, int offl,
8643                                 operand *result, int offr,
8644                                 int shCount, int sign)
8645 {
8646   int same;
8647
8648   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8649
8650   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8651
8652   /* Copy the msb into the carry if signed. */
8653   if(sign) {
8654     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8655     return;
8656   }
8657
8658
8659
8660   switch(shCount) {
8661   case 1:
8662     emitCLRC;
8663     if(same) 
8664       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8665     else {
8666       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8667       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8668     }
8669     break;
8670   case 2:
8671     emitCLRC;
8672     if(same) {
8673       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8674     } else {
8675       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8676       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677     }
8678     emitCLRC;
8679     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8680
8681     break;
8682   case 3:
8683     if(same)
8684       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8685     else {
8686       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8687       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8688     }
8689
8690     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8691     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8692     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8693     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694     break;
8695       
8696   case 4:
8697     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8698     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8699     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8700     break;
8701
8702   case 5:
8703     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8704     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8706     //emitCLRC;
8707     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8708
8709     break;
8710   case 6:
8711
8712     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8713     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8714     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8715     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8716     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8717     break;
8718
8719   case 7:
8720
8721     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8722     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8723     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8724
8725     break;
8726
8727   default:
8728     break;
8729   }
8730 }
8731
8732 /*-----------------------------------------------------------------*/
8733 /* shiftL1Left2Result - shift left one byte from left to result    */
8734 /*-----------------------------------------------------------------*/
8735 static void shiftL1Left2Result (operand *left, int offl,
8736                                 operand *result, int offr, int shCount)
8737 {
8738   int same;
8739
8740   //    char *l;
8741   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8742
8743   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8744   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8745     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8746     //    MOVA(l);
8747     /* shift left accumulator */
8748     //AccLsh(shCount); // don't comment out just yet...
8749   //    pic16_aopPut(AOP(result),"a",offr);
8750
8751   switch(shCount) {
8752   case 1:
8753     /* Shift left 1 bit position */
8754     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8755     if(same) {
8756       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8757     } else {
8758       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8759       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8760     }
8761     break;
8762   case 2:
8763     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8764     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8765     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8766     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8767     break;
8768   case 3:
8769     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8770     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8771     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8772     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8773     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8774     break;
8775   case 4:
8776     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8777     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8778     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8779     break;
8780   case 5:
8781     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8783     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785     break;
8786   case 6:
8787     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8789     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8790     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8791     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8792     break;
8793   case 7:
8794     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8796     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8797     break;
8798
8799   default:
8800     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8801   }
8802
8803 }
8804
8805 /*-----------------------------------------------------------------*/
8806 /* movLeft2Result - move byte from left to result                  */
8807 /*-----------------------------------------------------------------*/
8808 static void movLeft2Result (operand *left, int offl,
8809                             operand *result, int offr)
8810 {
8811   char *l;
8812   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8813   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8814     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8815
8816     if (*l == '@' && (IS_AOP_PREG(result))) {
8817       pic16_emitcode("mov","a,%s",l);
8818       pic16_aopPut(AOP(result),"a",offr);
8819     } else {
8820       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8821       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8822     }
8823   }
8824 }
8825
8826 /*-----------------------------------------------------------------*/
8827 /* shiftL2Left2Result - shift left two bytes from left to result   */
8828 /*-----------------------------------------------------------------*/
8829 static void shiftL2Left2Result (operand *left, int offl,
8830                                 operand *result, int offr, int shCount)
8831 {
8832   int same = pic16_sameRegs(AOP(result), AOP(left));
8833   int i;
8834
8835   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8836
8837   if (same && (offl != offr)) { // shift bytes
8838     if (offr > offl) {
8839        for(i=1;i>-1;i--) {
8840          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8841          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8842        }
8843     } else { // just treat as different later on
8844                 same = 0;
8845     }
8846   }
8847
8848   if(same) {
8849     switch(shCount) {
8850     case 0:
8851       break;
8852     case 1:
8853     case 2:
8854     case 3:
8855
8856       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8857       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8858       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8859
8860       while(--shCount) {
8861                 emitCLRC;
8862                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8863                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8864       }
8865
8866       break;
8867     case 4:
8868     case 5:
8869       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8870       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8871       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8872       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8873       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8874       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8875       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8876       if(shCount >=5) {
8877                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8878                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8879       }
8880       break;
8881     case 6:
8882       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8883       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8884       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8885       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8886       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8887       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8888       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8889       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8890       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8891       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8892       break;
8893     case 7:
8894       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8895       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8896       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8897       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8898       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8899     }
8900
8901   } else {
8902     switch(shCount) {
8903     case 0:
8904       break;
8905     case 1:
8906     case 2:
8907     case 3:
8908       /* note, use a mov/add for the shift since the mov has a
8909          chance of getting optimized out */
8910       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8911       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8912       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8913       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8914       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8915
8916       while(--shCount) {
8917                 emitCLRC;
8918                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8919                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8920       }
8921       break;
8922
8923     case 4:
8924     case 5:
8925       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8926       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8927       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8928       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8929       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8930       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8931       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8932       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8933
8934
8935       if(shCount == 5) {
8936                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8938       }
8939       break;
8940     case 6:
8941       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8942       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8943       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8944       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8945
8946       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8947       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8948       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8949       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8950       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8953       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8954       break;
8955     case 7:
8956       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8957       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8958       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8960       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8961     }
8962   }
8963
8964 }
8965 /*-----------------------------------------------------------------*/
8966 /* shiftR2Left2Result - shift right two bytes from left to result  */
8967 /*-----------------------------------------------------------------*/
8968 static void shiftR2Left2Result (operand *left, int offl,
8969                                 operand *result, int offr,
8970                                 int shCount, int sign)
8971 {
8972   int same = pic16_sameRegs(AOP(result), AOP(left));
8973   int i;
8974   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8975
8976   if (same && (offl != offr)) { // shift right bytes
8977     if (offr < offl) {
8978        for(i=0;i<2;i++) {
8979          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8980          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8981        }
8982     } else { // just treat as different later on
8983                 same = 0;
8984     }
8985   }
8986
8987   switch(shCount) {
8988   case 0:
8989     break;
8990   case 1:
8991   case 2:
8992   case 3:
8993     if(sign)
8994       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8995     else
8996       emitCLRC;
8997
8998     if(same) {
8999       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9000       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9001     } else {
9002       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9003       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9004       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9005       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9006     }
9007
9008     while(--shCount) {
9009       if(sign)
9010                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9011       else
9012                 emitCLRC;
9013       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9014       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9015     }
9016     break;
9017   case 4:
9018   case 5:
9019     if(same) {
9020
9021       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9022       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9023       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9024
9025       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9026       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9028       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9029     } else {
9030       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9031       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9032       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9033
9034       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9035       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9036       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9037       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9038       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9039     }
9040
9041     if(shCount >=5) {
9042       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9044     }
9045
9046     if(sign) {
9047       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9048       pic16_emitpcode(POC_BTFSC, 
9049                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9050       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9051     }
9052
9053     break;
9054
9055   case 6:
9056     if(same) {
9057
9058       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9059       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9060
9061       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9062       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9063       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9064       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9065       if(sign) {
9066         pic16_emitpcode(POC_BTFSC, 
9067                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9068         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9069       }
9070       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9071       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9072       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9073       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9074     } else {
9075       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9076       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9077       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9078       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9079       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9080       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9081       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9082       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9083       if(sign) {
9084         pic16_emitpcode(POC_BTFSC, 
9085                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9086         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9087       }
9088       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9089       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9090
9091         
9092     }
9093
9094     break;
9095   case 7:
9096     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9097     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9098     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9099     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9100     if(sign) {
9101       emitSKPNC;
9102       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9103     } else 
9104       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9105   }
9106 }
9107
9108
9109 /*-----------------------------------------------------------------*/
9110 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9111 /*-----------------------------------------------------------------*/
9112 static void shiftLLeftOrResult (operand *left, int offl,
9113                                 operand *result, int offr, int shCount)
9114 {
9115     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9116
9117     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9118     /* shift left accumulator */
9119     AccLsh(shCount);
9120     /* or with result */
9121     /* back to result */
9122     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9123 }
9124
9125 /*-----------------------------------------------------------------*/
9126 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9127 /*-----------------------------------------------------------------*/
9128 static void shiftRLeftOrResult (operand *left, int offl,
9129                                 operand *result, int offr, int shCount)
9130 {
9131     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9132     
9133     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9134     /* shift right accumulator */
9135     AccRsh(shCount, 1);
9136     /* or with result */
9137     /* back to result */
9138     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9139 }
9140
9141 /*-----------------------------------------------------------------*/
9142 /* genlshOne - left shift a one byte quantity by known count       */
9143 /*-----------------------------------------------------------------*/
9144 static void genlshOne (operand *result, operand *left, int shCount)
9145 {       
9146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9147     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9148 }
9149
9150 /*-----------------------------------------------------------------*/
9151 /* genlshTwo - left shift two bytes by known amount != 0           */
9152 /*-----------------------------------------------------------------*/
9153 static void genlshTwo (operand *result,operand *left, int shCount)
9154 {
9155     int size;
9156     
9157     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9158     size = pic16_getDataSize(result);
9159
9160     /* if shCount >= 8 */
9161     if (shCount >= 8) {
9162         shCount -= 8 ;
9163
9164         if (size > 1){
9165             if (shCount)
9166                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9167             else 
9168                 movLeft2Result(left, LSB, result, MSB16);
9169         }
9170         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9171     }
9172
9173     /*  1 <= shCount <= 7 */
9174     else {  
9175         if(size == 1)
9176             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9177         else 
9178             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9179     }
9180 }
9181
9182 /*-----------------------------------------------------------------*/
9183 /* shiftLLong - shift left one long from left to result            */
9184 /* offr = LSB or MSB16                                             */
9185 /*-----------------------------------------------------------------*/
9186 static void shiftLLong (operand *left, operand *result, int offr )
9187 {
9188     int size = AOP_SIZE(result);
9189     int same = pic16_sameRegs(AOP(left),AOP(result));
9190         int i;
9191
9192     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9193
9194         if (same && (offr == MSB16)) { //shift one byte
9195                 for(i=size-1;i>=MSB16;i--) {
9196                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9197                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9198                 }
9199         } else {
9200                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9201         }
9202         
9203     if (size > LSB+offr ){
9204                 if (same) {
9205                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9206                 } else {
9207                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9208                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9209                 }
9210          }
9211
9212     if(size > MSB16+offr){
9213                 if (same) {
9214                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9215                 } else {
9216                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9217                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9218                 }
9219     }
9220
9221     if(size > MSB24+offr){
9222                 if (same) {
9223                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9224                 } else {
9225                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9226                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9227                 }
9228     }
9229
9230     if(size > MSB32+offr){
9231                 if (same) {
9232                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9233                 } else {
9234                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9235                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9236                 }
9237     }
9238     if(offr != LSB)
9239                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9240
9241 }
9242
9243 /*-----------------------------------------------------------------*/
9244 /* genlshFour - shift four byte by a known amount != 0             */
9245 /*-----------------------------------------------------------------*/
9246 static void genlshFour (operand *result, operand *left, int shCount)
9247 {
9248     int size;
9249
9250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9251     size = AOP_SIZE(result);
9252
9253     /* if shifting more that 3 bytes */
9254     if (shCount >= 24 ) {
9255         shCount -= 24;
9256         if (shCount)
9257             /* lowest order of left goes to the highest
9258             order of the destination */
9259             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9260         else
9261             movLeft2Result(left, LSB, result, MSB32);
9262
9263                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9264                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9265                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9266
9267         return;
9268     }
9269
9270     /* more than two bytes */
9271     else if ( shCount >= 16 ) {
9272         /* lower order two bytes goes to higher order two bytes */
9273         shCount -= 16;
9274         /* if some more remaining */
9275         if (shCount)
9276             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9277         else {
9278             movLeft2Result(left, MSB16, result, MSB32);
9279             movLeft2Result(left, LSB, result, MSB24);
9280         }
9281                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9282                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9283         return;
9284     }    
9285
9286     /* if more than 1 byte */
9287     else if ( shCount >= 8 ) {
9288         /* lower order three bytes goes to higher order  three bytes */
9289         shCount -= 8;
9290         if(size == 2){
9291             if(shCount)
9292                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9293             else
9294                 movLeft2Result(left, LSB, result, MSB16);
9295         }
9296         else{   /* size = 4 */
9297             if(shCount == 0){
9298                 movLeft2Result(left, MSB24, result, MSB32);
9299                 movLeft2Result(left, MSB16, result, MSB24);
9300                 movLeft2Result(left, LSB, result, MSB16);
9301                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9302             }
9303             else if(shCount == 1)
9304                 shiftLLong(left, result, MSB16);
9305             else{
9306                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9307                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9308                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9309                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9310             }
9311         }
9312     }
9313
9314     /* 1 <= shCount <= 7 */
9315     else if(shCount <= 3)
9316     { 
9317         shiftLLong(left, result, LSB);
9318         while(--shCount >= 1)
9319             shiftLLong(result, result, LSB);
9320     }
9321     /* 3 <= shCount <= 7, optimize */
9322     else{
9323         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9324         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9325         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9326     }
9327 }
9328
9329 /*-----------------------------------------------------------------*/
9330 /* genLeftShiftLiteral - left shifting by known count              */
9331 /*-----------------------------------------------------------------*/
9332 void pic16_genLeftShiftLiteral (operand *left,
9333                                  operand *right,
9334                                  operand *result,
9335                                  iCode *ic)
9336 {    
9337     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9338     int size;
9339
9340     FENTRY;
9341     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9342     pic16_freeAsmop(right,NULL,ic,TRUE);
9343
9344     pic16_aopOp(left,ic,FALSE);
9345     pic16_aopOp(result,ic,TRUE);
9346
9347     size = getSize(operandType(result));
9348
9349 #if VIEW_SIZE
9350     pic16_emitcode("; shift left ","result %d, left %d",size,
9351              AOP_SIZE(left));
9352 #endif
9353
9354     /* I suppose that the left size >= result size */
9355     if(shCount == 0){
9356         while(size--){
9357             movLeft2Result(left, size, result, size);
9358         }
9359     }
9360
9361     else if(shCount >= (size * 8))
9362         while(size--)
9363             pic16_aopPut(AOP(result),zero,size);
9364     else{
9365         switch (size) {
9366             case 1:
9367                 genlshOne (result,left,shCount);
9368                 break;
9369
9370             case 2:
9371             case 3:
9372                 genlshTwo (result,left,shCount);
9373                 break;
9374
9375             case 4:
9376                 genlshFour (result,left,shCount);
9377                 break;
9378         }
9379     }
9380     pic16_freeAsmop(left,NULL,ic,TRUE);
9381     pic16_freeAsmop(result,NULL,ic,TRUE);
9382 }
9383
9384 /*-----------------------------------------------------------------*
9385  * genMultiAsm - repeat assembly instruction for size of register.
9386  * if endian == 1, then the high byte (i.e base address + size of 
9387  * register) is used first else the low byte is used first;
9388  *-----------------------------------------------------------------*/
9389 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9390 {
9391
9392   int offset = 0;
9393
9394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9395
9396   if(!reg)
9397     return;
9398
9399   if(!endian) {
9400     endian = 1;
9401   } else {
9402     endian = -1;
9403     offset = size-1;
9404   }
9405
9406   while(size--) {
9407     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9408     offset += endian;
9409   }
9410
9411 }
9412
9413 #if !(USE_GENERIC_SIGNED_SHIFT)
9414 /*-----------------------------------------------------------------*/
9415 /* genLeftShift - generates code for left shifting                 */
9416 /*-----------------------------------------------------------------*/
9417 static void genLeftShift (iCode *ic)
9418 {
9419   operand *left,*right, *result;
9420   int size, offset;
9421 //  char *l;
9422   symbol *tlbl , *tlbl1;
9423   pCodeOp *pctemp;
9424
9425   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9426
9427   right = IC_RIGHT(ic);
9428   left  = IC_LEFT(ic);
9429   result = IC_RESULT(ic);
9430
9431   pic16_aopOp(right,ic,FALSE);
9432
9433   /* if the shift count is known then do it 
9434      as efficiently as possible */
9435   if (AOP_TYPE(right) == AOP_LIT) {
9436     pic16_genLeftShiftLiteral (left,right,result,ic);
9437     return ;
9438   }
9439
9440   /* shift count is unknown then we have to form
9441    * a loop. Get the loop count in WREG : Note: we take
9442    * only the lower order byte since shifting
9443    * more than 32 bits make no sense anyway, ( the
9444    * largest size of an object can be only 32 bits ) */
9445   
9446   pic16_aopOp(left,ic,FALSE);
9447   pic16_aopOp(result,ic,FALSE);
9448
9449   /* now move the left to the result if they are not the
9450    * same, and if size > 1,
9451    * and if right is not same to result (!!!) -- VR */
9452   if (!pic16_sameRegs(AOP(left),AOP(result))
9453       && (AOP_SIZE(result) > 1)) {
9454
9455     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9456
9457     size = AOP_SIZE(result);
9458     offset=0;
9459     while (size--) {
9460
9461 #if 0
9462       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9463       if (*l == '@' && (IS_AOP_PREG(result))) {
9464
9465           pic16_emitcode("mov","a,%s",l);
9466           pic16_aopPut(AOP(result),"a",offset);
9467       } else
9468 #endif
9469       {
9470         /* we don't know if left is a literal or a register, take care -- VR */
9471         pic16_mov2f(AOP(result), AOP(left), offset);
9472       }
9473       offset++;
9474     }
9475   }
9476
9477   size = AOP_SIZE(result);
9478
9479   /* if it is only one byte then */
9480   if (size == 1) {
9481     if(optimized_for_speed) {
9482       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9483       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9484       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9485       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9486       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9487       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9488       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9489       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9490       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9491       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9492       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9493       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9494     } else {
9495
9496       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497
9498       tlbl = newiTempLabel(NULL);
9499
9500 #if 1
9501       /* this is already done, why change it? */
9502       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9503                 pic16_mov2f(AOP(result), AOP(left), 0);
9504       }
9505 #endif
9506
9507       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9508       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9509       pic16_emitpLabel(tlbl->key);
9510       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9511       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9512       emitSKPC;
9513       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9514     }
9515     goto release ;
9516   }
9517     
9518   if (pic16_sameRegs(AOP(left),AOP(result))) {
9519
9520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9521     
9522     tlbl = newiTempLabel(NULL);
9523     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9524     genMultiAsm(POC_RRCF, result, size,1);
9525     pic16_emitpLabel(tlbl->key);
9526     genMultiAsm(POC_RLCF, result, size,0);
9527     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9528     emitSKPC;
9529     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9530     goto release;
9531   }
9532
9533   //tlbl = newiTempLabel(NULL);
9534   //offset = 0 ;   
9535   //tlbl1 = newiTempLabel(NULL);
9536
9537   //reAdjustPreg(AOP(result));    
9538     
9539   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9540   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9541   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9542   //MOVA(l);
9543   //pic16_emitcode("add","a,acc");         
9544   //pic16_aopPut(AOP(result),"a",offset++);
9545   //while (--size) {
9546   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9547   //  MOVA(l);
9548   //  pic16_emitcode("rlc","a");         
9549   //  pic16_aopPut(AOP(result),"a",offset++);
9550   //}
9551   //reAdjustPreg(AOP(result));
9552
9553   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9554   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9555
9556
9557   tlbl = newiTempLabel(NULL);
9558   tlbl1= newiTempLabel(NULL);
9559
9560   size = AOP_SIZE(result);
9561   offset = 1;
9562
9563   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9564
9565   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9566
9567   /* offset should be 0, 1 or 3 */
9568   
9569   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9570   emitSKPNZ;
9571   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9572
9573   pic16_emitpcode(POC_MOVWF, pctemp);
9574
9575
9576   pic16_emitpLabel(tlbl->key);
9577
9578   emitCLRC;
9579   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9580   while(--size)
9581     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9582
9583   pic16_emitpcode(POC_DECFSZ,  pctemp);
9584   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9585   pic16_emitpLabel(tlbl1->key);
9586
9587   pic16_popReleaseTempReg(pctemp,1);
9588
9589
9590  release:
9591   pic16_freeAsmop (right,NULL,ic,TRUE);
9592   pic16_freeAsmop(left,NULL,ic,TRUE);
9593   pic16_freeAsmop(result,NULL,ic,TRUE);
9594 }
9595 #endif
9596
9597
9598 #if 0
9599 #error old code (left here for reference)
9600 /*-----------------------------------------------------------------*/
9601 /* genLeftShift - generates code for left shifting                 */
9602 /*-----------------------------------------------------------------*/
9603 static void genLeftShift (iCode *ic)
9604 {
9605   operand *left,*right, *result;
9606   int size, offset;
9607   char *l;
9608   symbol *tlbl , *tlbl1;
9609   pCodeOp *pctemp;
9610
9611   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9612
9613   right = IC_RIGHT(ic);
9614   left  = IC_LEFT(ic);
9615   result = IC_RESULT(ic);
9616
9617   pic16_aopOp(right,ic,FALSE);
9618
9619   /* if the shift count is known then do it 
9620      as efficiently as possible */
9621   if (AOP_TYPE(right) == AOP_LIT) {
9622     pic16_genLeftShiftLiteral (left,right,result,ic);
9623     return ;
9624   }
9625
9626   /* shift count is unknown then we have to form 
9627      a loop get the loop count in B : Note: we take
9628      only the lower order byte since shifting
9629      more that 32 bits make no sense anyway, ( the
9630      largest size of an object can be only 32 bits ) */  
9631
9632     
9633   pic16_aopOp(left,ic,FALSE);
9634   pic16_aopOp(result,ic,FALSE);
9635
9636   /* now move the left to the result if they are not the
9637      same */
9638   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9639       AOP_SIZE(result) > 1) {
9640
9641     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9642
9643     size = AOP_SIZE(result);
9644     offset=0;
9645     while (size--) {
9646       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9647       if (*l == '@' && (IS_AOP_PREG(result))) {
9648
9649         pic16_emitcode("mov","a,%s",l);
9650         pic16_aopPut(AOP(result),"a",offset);
9651       } else {
9652
9653         /* we don't know if left is a literal or a register, take care -- VR */
9654         pic16_mov2f(AOP(result), AOP(left), offset);
9655       }
9656       offset++;
9657     }
9658   }
9659
9660   size = AOP_SIZE(result);
9661
9662   /* if it is only one byte then */
9663   if (size == 1) {
9664     if(optimized_for_speed) {
9665       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9666       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9667       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9668       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9669       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9670       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9671       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9672       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9673       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9674       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9675       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9676       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9677     } else {
9678
9679       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9680
9681       tlbl = newiTempLabel(NULL);
9682       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9683                 pic16_mov2f(AOP(result), AOP(left), 0);
9684                 
9685 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9686 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9687       }
9688
9689       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9690       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9691       pic16_emitpLabel(tlbl->key);
9692       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9693       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9694       emitSKPC;
9695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9696     }
9697     goto release ;
9698   }
9699     
9700   if (pic16_sameRegs(AOP(left),AOP(result))) {
9701
9702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9703     
9704     tlbl = newiTempLabel(NULL);
9705     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9706     genMultiAsm(POC_RRCF, result, size,1);
9707     pic16_emitpLabel(tlbl->key);
9708     genMultiAsm(POC_RLCF, result, size,0);
9709     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9710     emitSKPC;
9711     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9712     goto release;
9713   }
9714
9715   //tlbl = newiTempLabel(NULL);
9716   //offset = 0 ;   
9717   //tlbl1 = newiTempLabel(NULL);
9718
9719   //reAdjustPreg(AOP(result));    
9720     
9721   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9722   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9723   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9724   //MOVA(l);
9725   //pic16_emitcode("add","a,acc");         
9726   //pic16_aopPut(AOP(result),"a",offset++);
9727   //while (--size) {
9728   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9729   //  MOVA(l);
9730   //  pic16_emitcode("rlc","a");         
9731   //  pic16_aopPut(AOP(result),"a",offset++);
9732   //}
9733   //reAdjustPreg(AOP(result));
9734
9735   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9736   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9737
9738
9739   tlbl = newiTempLabel(NULL);
9740   tlbl1= newiTempLabel(NULL);
9741
9742   size = AOP_SIZE(result);
9743   offset = 1;
9744
9745   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9746
9747   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9748
9749   /* offset should be 0, 1 or 3 */
9750   
9751   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9752   emitSKPNZ;
9753   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9754
9755   pic16_emitpcode(POC_MOVWF, pctemp);
9756
9757
9758   pic16_emitpLabel(tlbl->key);
9759
9760   emitCLRC;
9761   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9762   while(--size)
9763     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9764
9765   pic16_emitpcode(POC_DECFSZ,  pctemp);
9766   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9767   pic16_emitpLabel(tlbl1->key);
9768
9769   pic16_popReleaseTempReg(pctemp,1);
9770
9771
9772  release:
9773   pic16_freeAsmop (right,NULL,ic,TRUE);
9774   pic16_freeAsmop(left,NULL,ic,TRUE);
9775   pic16_freeAsmop(result,NULL,ic,TRUE);
9776 }
9777 #endif
9778
9779 /*-----------------------------------------------------------------*/
9780 /* genrshOne - right shift a one byte quantity by known count      */
9781 /*-----------------------------------------------------------------*/
9782 static void genrshOne (operand *result, operand *left,
9783                        int shCount, int sign)
9784 {
9785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9786     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9787 }
9788
9789 /*-----------------------------------------------------------------*/
9790 /* genrshTwo - right shift two bytes by known amount != 0          */
9791 /*-----------------------------------------------------------------*/
9792 static void genrshTwo (operand *result,operand *left,
9793                        int shCount, int sign)
9794 {
9795   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9796   /* if shCount >= 8 */
9797   if (shCount >= 8) {
9798     shCount -= 8 ;
9799     if (shCount)
9800       shiftR1Left2Result(left, MSB16, result, LSB,
9801                          shCount, sign);
9802     else
9803       movLeft2Result(left, MSB16, result, LSB);
9804
9805     pic16_addSign (result, 1, sign);
9806   }
9807
9808   /*  1 <= shCount <= 7 */
9809   else
9810     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9811 }
9812
9813 /*-----------------------------------------------------------------*/
9814 /* shiftRLong - shift right one long from left to result           */
9815 /* offl = LSB or MSB16                                             */
9816 /*-----------------------------------------------------------------*/
9817 static void shiftRLong (operand *left, int offl,
9818                         operand *result, int sign)
9819 {
9820     int size = AOP_SIZE(result);
9821     int same = pic16_sameRegs(AOP(left),AOP(result));
9822     int i;
9823     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9824
9825         if (same && (offl == MSB16)) { //shift one byte right
9826                 for(i=MSB16;i<size;i++) {
9827                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9828                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9829                 }
9830         }
9831
9832     if(sign)
9833                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9834         else
9835                 emitCLRC;
9836
9837         if (same) {
9838                 if (offl == LSB)
9839                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9840         } else {
9841         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9842         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9843         }
9844
9845     if(offl == MSB16) {
9846         /* add sign of "a" */
9847         pic16_addSign(result, MSB32, sign);
9848         }
9849
9850         if (same) {
9851         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9852         } else {
9853         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9854         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9855         }
9856         
9857         if (same) {
9858         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9859         } else {
9860         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9861         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9862         }
9863
9864         if (same) {
9865         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9866         } else {
9867         if(offl == LSB){
9868                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9869                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9870         }
9871         }
9872 }
9873
9874 /*-----------------------------------------------------------------*/
9875 /* genrshFour - shift four byte by a known amount != 0             */
9876 /*-----------------------------------------------------------------*/
9877 static void genrshFour (operand *result, operand *left,
9878                         int shCount, int sign)
9879 {
9880   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9881   /* if shifting more that 3 bytes */
9882   if(shCount >= 24 ) {
9883     shCount -= 24;
9884     if(shCount)
9885       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9886     else
9887       movLeft2Result(left, MSB32, result, LSB);
9888
9889     pic16_addSign(result, MSB16, sign);
9890   }
9891   else if(shCount >= 16){
9892     shCount -= 16;
9893     if(shCount)
9894       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9895     else{
9896       movLeft2Result(left, MSB24, result, LSB);
9897       movLeft2Result(left, MSB32, result, MSB16);
9898     }
9899     pic16_addSign(result, MSB24, sign);
9900   }
9901   else if(shCount >= 8){
9902     shCount -= 8;
9903     if(shCount == 1)
9904       shiftRLong(left, MSB16, result, sign);
9905     else if(shCount == 0){
9906       movLeft2Result(left, MSB16, result, LSB);
9907       movLeft2Result(left, MSB24, result, MSB16);
9908       movLeft2Result(left, MSB32, result, MSB24);
9909       pic16_addSign(result, MSB32, sign);
9910     }
9911     else{ //shcount >= 2
9912       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9913       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9914       /* the last shift is signed */
9915       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9916       pic16_addSign(result, MSB32, sign);
9917     }
9918   }
9919   else{   /* 1 <= shCount <= 7 */
9920     if(shCount <= 2){
9921       shiftRLong(left, LSB, result, sign);
9922       if(shCount == 2)
9923         shiftRLong(result, LSB, result, sign);
9924     }
9925     else{
9926       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9927       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9928       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9929     }
9930   }
9931 }
9932
9933 /*-----------------------------------------------------------------*/
9934 /* genRightShiftLiteral - right shifting by known count            */
9935 /*-----------------------------------------------------------------*/
9936 static void genRightShiftLiteral (operand *left,
9937                                   operand *right,
9938                                   operand *result,
9939                                   iCode *ic,
9940                                   int sign)
9941 {    
9942   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9943   int lsize,res_size;
9944
9945   pic16_freeAsmop(right,NULL,ic,TRUE);
9946
9947   pic16_aopOp(left,ic,FALSE);
9948   pic16_aopOp(result,ic,TRUE);
9949
9950   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9951
9952 #if VIEW_SIZE
9953   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9954                  AOP_SIZE(left));
9955 #endif
9956
9957   lsize = pic16_getDataSize(left);
9958   res_size = pic16_getDataSize(result);
9959   /* test the LEFT size !!! */
9960
9961   /* I suppose that the left size >= result size */
9962   if(shCount == 0){
9963     assert (res_size <= lsize);
9964     while (res_size--) {
9965       pic16_mov2f (AOP(result), AOP(left), res_size);
9966     } // for
9967   }
9968
9969   else if(shCount >= (lsize * 8)){
9970
9971     if(res_size == 1) {
9972       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9973       if(sign) {
9974         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9975         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9976       }
9977     } else {
9978
9979       if(sign) {
9980         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9981         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9982         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9983         while(res_size--)
9984           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9985
9986       } else {
9987
9988         while(res_size--)
9989           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9990       }
9991     }
9992   } else {
9993
9994     switch (res_size) {
9995     case 1:
9996       genrshOne (result,left,shCount,sign);
9997       break;
9998
9999     case 2:
10000       genrshTwo (result,left,shCount,sign);
10001       break;
10002
10003     case 4:
10004       genrshFour (result,left,shCount,sign);
10005       break;
10006     default :
10007       break;
10008     }
10009
10010   }
10011
10012   pic16_freeAsmop(left,NULL,ic,TRUE);
10013   pic16_freeAsmop(result,NULL,ic,TRUE);
10014 }
10015
10016 #if !(USE_GENERIC_SIGNED_SHIFT)
10017 /*-----------------------------------------------------------------*/
10018 /* genSignedRightShift - right shift of signed number              */
10019 /*-----------------------------------------------------------------*/
10020 static void genSignedRightShift (iCode *ic)
10021 {
10022   operand *right, *left, *result;
10023   int size, offset;
10024   //  char *l;
10025   symbol *tlbl, *tlbl1 ;
10026   pCodeOp *pctemp;
10027
10028   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10029
10030   /* we do it the hard way put the shift count in b
10031      and loop thru preserving the sign */
10032   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10033
10034   right = IC_RIGHT(ic);
10035   left  = IC_LEFT(ic);
10036   result = IC_RESULT(ic);
10037
10038   pic16_aopOp(right,ic,FALSE);  
10039   pic16_aopOp(left,ic,FALSE);
10040   pic16_aopOp(result,ic,FALSE);
10041
10042
10043   if ( AOP_TYPE(right) == AOP_LIT) {
10044     genRightShiftLiteral (left,right,result,ic,1);
10045     return ;
10046   }
10047   /* shift count is unknown then we have to form 
10048      a loop get the loop count in B : Note: we take
10049      only the lower order byte since shifting
10050      more that 32 bits make no sense anyway, ( the
10051      largest size of an object can be only 32 bits ) */  
10052
10053   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10054   //pic16_emitcode("inc","b");
10055   //pic16_freeAsmop (right,NULL,ic,TRUE);
10056   //pic16_aopOp(left,ic,FALSE);
10057   //pic16_aopOp(result,ic,FALSE);
10058
10059   /* now move the left to the result if they are not the
10060      same */
10061   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10062       AOP_SIZE(result) > 1) {
10063
10064     size = AOP_SIZE(result);
10065     offset=0;
10066     while (size--) { 
10067       /*
10068         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10069         if (*l == '@' && IS_AOP_PREG(result)) {
10070
10071         pic16_emitcode("mov","a,%s",l);
10072         pic16_aopPut(AOP(result),"a",offset);
10073         } else
10074         pic16_aopPut(AOP(result),l,offset);
10075       */
10076       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10077       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10078
10079       offset++;
10080     }
10081   }
10082
10083   /* mov the highest order bit to OVR */    
10084   tlbl = newiTempLabel(NULL);
10085   tlbl1= newiTempLabel(NULL);
10086
10087   size = AOP_SIZE(result);
10088   offset = size - 1;
10089
10090   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10091
10092   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10093
10094   /* offset should be 0, 1 or 3 */
10095   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10096   emitSKPNZ;
10097   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10098
10099   pic16_emitpcode(POC_MOVWF, pctemp);
10100
10101
10102   pic16_emitpLabel(tlbl->key);
10103
10104   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10105   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10106
10107   while(--size) {
10108     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10109   }
10110
10111   pic16_emitpcode(POC_DECFSZ,  pctemp);
10112   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10113   pic16_emitpLabel(tlbl1->key);
10114
10115   pic16_popReleaseTempReg(pctemp,1);
10116 #if 0
10117   size = AOP_SIZE(result);
10118   offset = size - 1;
10119   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10120   pic16_emitcode("rlc","a");
10121   pic16_emitcode("mov","ov,c");
10122   /* if it is only one byte then */
10123   if (size == 1) {
10124     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10125     MOVA(l);
10126     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10127     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10128     pic16_emitcode("mov","c,ov");
10129     pic16_emitcode("rrc","a");
10130     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10131     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10132     pic16_aopPut(AOP(result),"a",0);
10133     goto release ;
10134   }
10135
10136   reAdjustPreg(AOP(result));
10137   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10138   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10139   pic16_emitcode("mov","c,ov");
10140   while (size--) {
10141     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10142     MOVA(l);
10143     pic16_emitcode("rrc","a");         
10144     pic16_aopPut(AOP(result),"a",offset--);
10145   }
10146   reAdjustPreg(AOP(result));
10147   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10149
10150  release:
10151 #endif
10152
10153   pic16_freeAsmop(left,NULL,ic,TRUE);
10154   pic16_freeAsmop(result,NULL,ic,TRUE);
10155   pic16_freeAsmop(right,NULL,ic,TRUE);
10156 }
10157 #endif
10158
10159 #if !(USE_GENERIC_SIGNED_SHIFT)
10160 #warning This implementation of genRightShift() is incomplete!
10161 /*-----------------------------------------------------------------*/
10162 /* genRightShift - generate code for right shifting                */
10163 /*-----------------------------------------------------------------*/
10164 static void genRightShift (iCode *ic)
10165 {
10166     operand *right, *left, *result;
10167     sym_link *letype ;
10168     int size, offset;
10169     char *l;
10170     symbol *tlbl, *tlbl1 ;
10171
10172     /* if signed then we do it the hard way preserve the
10173     sign bit moving it inwards */
10174     letype = getSpec(operandType(IC_LEFT(ic)));
10175     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10176
10177     if (!SPEC_USIGN(letype)) {
10178         genSignedRightShift (ic);
10179         return ;
10180     }
10181
10182     /* signed & unsigned types are treated the same : i.e. the
10183     signed is NOT propagated inwards : quoting from the
10184     ANSI - standard : "for E1 >> E2, is equivalent to division
10185     by 2**E2 if unsigned or if it has a non-negative value,
10186     otherwise the result is implementation defined ", MY definition
10187     is that the sign does not get propagated */
10188
10189     right = IC_RIGHT(ic);
10190     left  = IC_LEFT(ic);
10191     result = IC_RESULT(ic);
10192
10193     pic16_aopOp(right,ic,FALSE);
10194
10195     /* if the shift count is known then do it 
10196     as efficiently as possible */
10197     if (AOP_TYPE(right) == AOP_LIT) {
10198         genRightShiftLiteral (left,right,result,ic, 0);
10199         return ;
10200     }
10201
10202     /* shift count is unknown then we have to form 
10203     a loop get the loop count in B : Note: we take
10204     only the lower order byte since shifting
10205     more that 32 bits make no sense anyway, ( the
10206     largest size of an object can be only 32 bits ) */  
10207
10208     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10209     pic16_emitcode("inc","b");
10210     pic16_aopOp(left,ic,FALSE);
10211     pic16_aopOp(result,ic,FALSE);
10212
10213     /* now move the left to the result if they are not the
10214     same */
10215     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10216         AOP_SIZE(result) > 1) {
10217
10218         size = AOP_SIZE(result);
10219         offset=0;
10220         while (size--) {
10221             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10222             if (*l == '@' && IS_AOP_PREG(result)) {
10223
10224                 pic16_emitcode("mov","a,%s",l);
10225                 pic16_aopPut(AOP(result),"a",offset);
10226             } else
10227                 pic16_aopPut(AOP(result),l,offset);
10228             offset++;
10229         }
10230     }
10231
10232     tlbl = newiTempLabel(NULL);
10233     tlbl1= newiTempLabel(NULL);
10234     size = AOP_SIZE(result);
10235     offset = size - 1;
10236
10237     /* if it is only one byte then */
10238     if (size == 1) {
10239
10240       tlbl = newiTempLabel(NULL);
10241       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10242         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10243         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10244       }
10245
10246       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10247       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10248       pic16_emitpLabel(tlbl->key);
10249       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10250       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10251       emitSKPC;
10252       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10253
10254       goto release ;
10255     }
10256
10257     reAdjustPreg(AOP(result));
10258     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10259     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10260     CLRC;
10261     while (size--) {
10262         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10263         MOVA(l);
10264         pic16_emitcode("rrc","a");         
10265         pic16_aopPut(AOP(result),"a",offset--);
10266     }
10267     reAdjustPreg(AOP(result));
10268
10269     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10270     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10271
10272 release:
10273     pic16_freeAsmop(left,NULL,ic,TRUE);
10274     pic16_freeAsmop (right,NULL,ic,TRUE);
10275     pic16_freeAsmop(result,NULL,ic,TRUE);
10276 }
10277 #endif
10278
10279 #if (USE_GENERIC_SIGNED_SHIFT)
10280 /*-----------------------------------------------------------------*/
10281 /* genGenericShift - generates code for left or right shifting     */
10282 /*-----------------------------------------------------------------*/
10283 static void genGenericShift (iCode *ic, int isShiftLeft) {
10284   operand *left,*right, *result;
10285   int offset;
10286   int sign, signedCount;
10287   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10288   PIC_OPCODE pos_shift, neg_shift;
10289
10290   FENTRY;
10291
10292   right = IC_RIGHT(ic);
10293   left  = IC_LEFT(ic);
10294   result = IC_RESULT(ic);
10295
10296   pic16_aopOp(right,ic,FALSE);
10297   pic16_aopOp(left,ic,FALSE);
10298   pic16_aopOp(result,ic,TRUE);
10299
10300   sign = !SPEC_USIGN(operandType (left));
10301   signedCount = !SPEC_USIGN(operandType (right));
10302
10303   /* if the shift count is known then do it 
10304      as efficiently as possible */
10305   if (AOP_TYPE(right) == AOP_LIT) {
10306     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10307     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10308     // we should modify right->aopu.aop_lit here!
10309     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10310     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10311     if (isShiftLeft)
10312       pic16_genLeftShiftLiteral (left,right,result,ic);
10313     else
10314       genRightShiftLiteral (left,right,result,ic, sign);
10315
10316     goto release;
10317   } // if (right is literal)
10318
10319   /* shift count is unknown then we have to form a loop.
10320    * Note: we take only the lower order byte since shifting
10321    * more than 32 bits make no sense anyway, ( the
10322    * largest size of an object can be only 32 bits )
10323    * Note: we perform arithmetic shifts if the left operand is
10324    * signed and we do an (effective) right shift, i. e. we
10325    * shift in the sign bit from the left. */
10326    
10327   label_complete = newiTempLabel ( NULL );
10328   label_loop_pos = newiTempLabel ( NULL );
10329   label_loop_neg = NULL;
10330   label_negative = NULL;
10331   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10332   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10333
10334   if (signedCount) {
10335     // additional labels needed
10336     label_loop_neg = newiTempLabel ( NULL );
10337     label_negative = newiTempLabel ( NULL );
10338   } // if
10339
10340   // copy source to result -- this will effectively truncate the left operand to the size of result!
10341   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10342   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10343   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10344     pic16_mov2f (AOP(result),AOP(left), offset);
10345   } // for
10346
10347   // if result is longer than left, fill with zeros (or sign)
10348   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10349     if (sign && AOP_SIZE(left) > 0) {
10350       // shift signed operand -- fill with sign
10351       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10352       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10353       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10354       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10355         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10356       } // for
10357     } else {
10358       // shift unsigned operand -- fill result with zeros
10359       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10360         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10361       } // for
10362     }
10363   } // if (size mismatch)
10364
10365   pic16_mov2w (AOP(right), 0);
10366   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10367   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10368   
10369 #if 0
10370   // perform a shift by one (shift count is positive)
10371   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10372   // 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])
10373   pic16_emitpLabel (label_loop_pos->key);
10374   emitCLRC;
10375   if (sign && (pos_shift == POC_RRCF)) {
10376     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10377     emitSETC;
10378   } // if
10379   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10380   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10381   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10382 #else
10383   // perform a shift by one (shift count is positive)
10384   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10385   // 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])
10386   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10387   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10388   emitCLRC;
10389   pic16_emitpLabel (label_loop_pos->key);
10390   if (sign && (pos_shift == POC_RRCF)) {
10391     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10392     emitSETC;
10393   } // if
10394   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10395   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10396   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10397   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10398 #endif
10399
10400   if (signedCount) {
10401     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10402
10403     pic16_emitpLabel (label_negative->key);
10404     // perform a shift by -1 (shift count is negative)
10405     // 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)
10406     emitCLRC;
10407     pic16_emitpLabel (label_loop_neg->key);
10408     if (sign && (neg_shift == POC_RRCF)) {
10409       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10410       emitSETC;
10411     } // if
10412     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10413     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10414     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10415     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10416   } // if (signedCount)
10417
10418   pic16_emitpLabel (label_complete->key);
10419
10420 release:
10421   pic16_freeAsmop (right,NULL,ic,TRUE);
10422   pic16_freeAsmop(left,NULL,ic,TRUE);
10423   pic16_freeAsmop(result,NULL,ic,TRUE);
10424 }
10425
10426 static void genLeftShift (iCode *ic) {
10427   genGenericShift (ic, 1);
10428 }
10429
10430 static void genRightShift (iCode *ic) {
10431   genGenericShift (ic, 0);
10432 }
10433 #endif
10434
10435
10436 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10437 void pic16_loadFSR0(operand *op, int lit)
10438 {
10439   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10440     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10441   } else {
10442     assert (!OP_SYMBOL(op)->remat);
10443     // set up FSR0 with address of result
10444     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10445     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10446   }
10447 }
10448
10449 /*----------------------------------------------------------------*/
10450 /* pic16_derefPtr - move one byte from the location ptr points to */
10451 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10452 /*                  to the location ptr points to (doWrite != 0)   */
10453 /*----------------------------------------------------------------*/
10454 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10455 {
10456   if (!IS_PTR(operandType(ptr)))
10457   {
10458     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10459     else pic16_mov2w (AOP(ptr), 0);
10460     return;
10461   }
10462
10463   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10464   /* We might determine pointer type right here: */
10465   p_type = DCL_TYPE(operandType(ptr));
10466
10467   switch (p_type) {
10468     case FPOINTER:
10469     case POINTER:
10470       if (!fsr0_setup || !*fsr0_setup)
10471       {
10472         pic16_loadFSR0( ptr, 0 );
10473         if (fsr0_setup) *fsr0_setup = 1;
10474       }
10475       if (doWrite)
10476         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10477       else
10478         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10479       break;
10480
10481     case GPOINTER:
10482       if (AOP(ptr)->aopu.aop_reg[2]) {
10483         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10484         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10485         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10486         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10487         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10488         pic16_callGenericPointerRW(doWrite, 1);
10489       } else {
10490         // data pointer (just 2 byte given)
10491         if (!fsr0_setup || !*fsr0_setup)
10492         {
10493           pic16_loadFSR0( ptr, 0 );
10494           if (fsr0_setup) *fsr0_setup = 1;
10495         }
10496         if (doWrite)
10497           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10498         else
10499           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10500       }
10501       break;
10502
10503     default:
10504       assert (0 && "invalid pointer type specified");
10505       break;
10506   }
10507 }
10508
10509 /*-----------------------------------------------------------------*/
10510 /* genUnpackBits - generates code for unpacking bits               */
10511 /*-----------------------------------------------------------------*/
10512 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10513 {    
10514   int shCnt ;
10515   sym_link *etype, *letype;
10516   int blen=0, bstr=0;
10517   int lbstr;
10518   int same;
10519   pCodeOp *op;
10520
10521   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10522   etype = getSpec(operandType(result));
10523   letype = getSpec(operandType(left));
10524
10525   //    if(IS_BITFIELD(etype)) {
10526   blen = SPEC_BLEN(etype);
10527   bstr = SPEC_BSTR(etype);
10528   //    }
10529
10530   lbstr = SPEC_BSTR( letype );
10531
10532   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10533       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10534
10535 #if 1
10536   if((blen == 1) && (bstr < 8)
10537       && (!IS_PTR(operandType(left)) || PIC_IS_DATA_PTR(operandType(left)))) {
10538     /* it is a single bit, so use the appropriate bit instructions */
10539     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10540
10541     same = pic16_sameRegs(AOP(left),AOP(result));
10542     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10543     pic16_emitpcode(POC_CLRF, op);
10544
10545     if(!IS_PTR(operandType(left))) {
10546       /* workaround to reduce the extra lfsr instruction */
10547       pic16_emitpcode(POC_BTFSC,
10548           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10549     } else {
10550       assert (PIC_IS_DATA_PTR (operandType(left)));
10551       pic16_loadFSR0 (left, 0);
10552       pic16_emitpcode(POC_BTFSC,
10553           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10554     }
10555
10556     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10557       /* unsigned bitfields result in either 0 or 1 */
10558       pic16_emitpcode(POC_INCF, op);
10559     } else {
10560       /* signed bitfields result in either 0 or -1 */
10561       pic16_emitpcode(POC_DECF, op);
10562     }
10563     if (same) {
10564       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10565     }
10566
10567     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10568     return;
10569   }
10570
10571 #endif
10572
10573   if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10574     // access symbol directly
10575     pic16_mov2w (AOP(left), 0);
10576   } else {
10577     pic16_derefPtr (left, ptype, 0, NULL);
10578   }
10579
10580   /* if we have bitdisplacement then it fits   */
10581   /* into this byte completely or if length is */
10582   /* less than a byte                          */
10583   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10584
10585     /* shift right acc */
10586     AccRsh(shCnt, 0);
10587
10588     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10589           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10590
10591     /* VR -- normally I would use the following, but since we use the hack,
10592      * to avoid the masking from AccRsh, why not mask it right now? */
10593
10594     /*
10595        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10596      */
10597
10598     /* extend signed bitfields to 8 bits */
10599     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10600     {
10601       assert (blen + bstr > 0);
10602       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10603       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10604     }
10605
10606     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10607
10608     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10609     return ;
10610   }
10611
10612   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10613   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10614   exit(-1);
10615
10616   return ;
10617 }
10618
10619
10620 static void genDataPointerGet(operand *left,
10621                               operand *result,
10622                               iCode *ic)
10623 {
10624   int size, offset = 0, leoffset=0 ;
10625
10626         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10627         pic16_aopOp(result, ic, TRUE);
10628
10629         FENTRY;
10630
10631         size = AOP_SIZE(result);
10632 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10633
10634
10635 #if 0
10636         /* The following tests may save a redudant movff instruction when
10637          * accessing unions */
10638          
10639         /* if they are the same */
10640         if (operandsEqu (left, result)) {
10641                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10642                 goto release;
10643         }
10644 #endif
10645
10646 #if 0
10647         /* if they are the same registers */
10648         if (pic16_sameRegs(AOP(left),AOP(result))) {
10649                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10650                 goto release;
10651         }
10652 #endif
10653
10654 #if 1
10655         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10656                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10657                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10658                 goto release;
10659         }
10660 #endif
10661
10662
10663 #if 0
10664         if ( AOP_TYPE(left) == AOP_PCODE) {
10665                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10666                                 AOP(left)->aopu.pcop->name,
10667                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10668                                 PCOR(AOP(left)->aopu.pcop)->instance:
10669                                 PCOI(AOP(left)->aopu.pcop)->offset);
10670         }
10671 #endif
10672
10673         if(AOP(left)->aopu.pcop->type == PO_DIR)
10674                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10675
10676         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10677
10678         while (size--) {
10679                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10680                 
10681 //              pic16_DumpOp("(result)",result);
10682                 if(is_LitAOp(AOP(result))) {
10683                         pic16_mov2w(AOP(left), offset); // patch 8
10684                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10685                 } else {
10686                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10687                                 pic16_popGet(AOP(left), offset), //patch 8
10688                                 pic16_popGet(AOP(result), offset)));
10689                 }
10690
10691                 offset++;
10692                 leoffset++;
10693         }
10694
10695 release:
10696     pic16_freeAsmop(result,NULL,ic,TRUE);
10697 }
10698
10699
10700
10701 /*-----------------------------------------------------------------*/
10702 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10703 /*-----------------------------------------------------------------*/
10704 static void genNearPointerGet (operand *left, 
10705                                operand *result, 
10706                                iCode *ic)
10707 {
10708 //  asmop *aop = NULL;
10709   //regs *preg = NULL ;
10710   sym_link *rtype, *retype;
10711   sym_link *ltype, *letype;
10712
10713     FENTRY;
10714     
10715     rtype = operandType(result);
10716     retype= getSpec(rtype);
10717     ltype = operandType(left);
10718     letype= getSpec(ltype);
10719     
10720     pic16_aopOp(left,ic,FALSE);
10721
10722 //    pic16_DumpOp("(left)",left);
10723 //    pic16_DumpOp("(result)",result);
10724
10725     /* if left is rematerialisable and
10726      * result is not bit variable type and
10727      * the left is pointer to data space i.e
10728      * lower 128 bytes of space */
10729     
10730     if (AOP_TYPE(left) == AOP_PCODE
10731       && !IS_BITFIELD(retype)
10732       && DCL_TYPE(ltype) == POINTER) {
10733
10734         genDataPointerGet (left,result,ic);
10735         pic16_freeAsmop(left, NULL, ic, TRUE);
10736         return ;
10737     }
10738     
10739     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10740     pic16_aopOp (result,ic,TRUE);
10741     
10742     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10743
10744 #if 1
10745     if(IS_BITFIELD( retype )
10746       && (SPEC_BLEN(operandType(result))==1)
10747     ) {
10748       iCode *nextic;
10749       pCodeOp *jop;
10750       int bitstrt, bytestrt;
10751
10752         /* if this is bitfield of size 1, see if we are checking the value
10753          * of a single bit in an if-statement,
10754          * if yes, then don't generate usual code, but execute the
10755          * genIfx directly -- VR */
10756
10757         nextic = ic->next;
10758
10759         /* CHECK: if next iCode is IFX
10760          * and current result operand is nextic's conditional operand
10761          * and current result operand live ranges ends at nextic's key number
10762          */
10763         if((nextic->op == IFX)
10764           && (result == IC_COND(nextic))
10765           && (OP_LIVETO(result) == nextic->seq)
10766           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10767           ) {
10768             /* everything is ok then */
10769             /* find a way to optimize the genIfx iCode */
10770
10771             bytestrt = SPEC_BSTR(operandType(result))/8;
10772             bitstrt = SPEC_BSTR(operandType(result))%8;
10773             
10774             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10775
10776             genIfxpCOpJump(nextic, jop);
10777             
10778             pic16_freeAsmop(left, NULL, ic, TRUE);
10779             pic16_freeAsmop(result, NULL, ic, TRUE);
10780             return;
10781         }
10782     }
10783 #endif
10784
10785     /* if bitfield then unpack the bits */
10786     if (IS_BITFIELD(letype)) 
10787       genUnpackBits (result, left, NULL, POINTER);
10788     else {
10789       /* we have can just get the values */
10790       int size = AOP_SIZE(result);
10791       int offset = 0;   
10792         
10793       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10794
10795       pic16_loadFSR0( left, 0 );
10796
10797       while(size--) {
10798         if(size) {
10799           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10800                 pic16_popGet(AOP(result), offset++)));
10801         } else {
10802           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10803                 pic16_popGet(AOP(result), offset++)));
10804         }
10805       }
10806     }
10807
10808 #if 0
10809     /* now some housekeeping stuff */
10810     if (aop) {
10811       /* we had to allocate for this iCode */
10812       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10813       pic16_freeAsmop(NULL,aop,ic,TRUE);
10814     } else { 
10815       /* we did not allocate which means left
10816        * already in a pointer register, then
10817        * if size > 0 && this could be used again
10818        * we have to point it back to where it 
10819        * belongs */
10820       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10821       if (AOP_SIZE(result) > 1
10822         && !OP_SYMBOL(left)->remat
10823         && ( OP_SYMBOL(left)->liveTo > ic->seq
10824             || ic->depth )) {
10825 //        int size = AOP_SIZE(result) - 1;
10826 //        while (size--)
10827 //          pic16_emitcode("dec","%s",rname);
10828         }
10829     }
10830 #endif
10831
10832     /* done */
10833     pic16_freeAsmop(left,NULL,ic,TRUE);
10834     pic16_freeAsmop(result,NULL,ic,TRUE);
10835 }
10836
10837 /*-----------------------------------------------------------------*/
10838 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10839 /*-----------------------------------------------------------------*/
10840 static void genPagedPointerGet (operand *left, 
10841                                operand *result, 
10842                                iCode *ic)
10843 {
10844     asmop *aop = NULL;
10845     regs *preg = NULL ;
10846     char *rname ;
10847     sym_link *rtype, *retype;    
10848
10849     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10850
10851     rtype = operandType(result);
10852     retype= getSpec(rtype);
10853     
10854     pic16_aopOp(left,ic,FALSE);
10855
10856   /* if the value is already in a pointer register
10857        then don't need anything more */
10858     if (!AOP_INPREG(AOP(left))) {
10859         /* otherwise get a free pointer register */
10860         aop = newAsmop(0);
10861         preg = getFreePtr(ic,&aop,FALSE);
10862         pic16_emitcode("mov","%s,%s",
10863                 preg->name,
10864                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10865         rname = preg->name ;
10866     } else
10867         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10868     
10869     pic16_freeAsmop(left,NULL,ic,TRUE);
10870     pic16_aopOp (result,ic,TRUE);
10871
10872     /* if bitfield then unpack the bits */
10873     if (IS_BITFIELD(retype)) 
10874         genUnpackBits (result,left,rname,PPOINTER);
10875     else {
10876         /* we have can just get the values */
10877         int size = AOP_SIZE(result);
10878         int offset = 0 ;        
10879         
10880         while (size--) {
10881             
10882             pic16_emitcode("movx","a,@%s",rname);
10883             pic16_aopPut(AOP(result),"a",offset);
10884             
10885             offset++ ;
10886             
10887             if (size)
10888                 pic16_emitcode("inc","%s",rname);
10889         }
10890     }
10891
10892     /* now some housekeeping stuff */
10893     if (aop) {
10894         /* we had to allocate for this iCode */
10895         pic16_freeAsmop(NULL,aop,ic,TRUE);
10896     } else { 
10897         /* we did not allocate which means left
10898            already in a pointer register, then
10899            if size > 0 && this could be used again
10900            we have to point it back to where it 
10901            belongs */
10902         if (AOP_SIZE(result) > 1 &&
10903             !OP_SYMBOL(left)->remat &&
10904             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10905               ic->depth )) {
10906             int size = AOP_SIZE(result) - 1;
10907             while (size--)
10908                 pic16_emitcode("dec","%s",rname);
10909         }
10910     }
10911
10912     /* done */
10913     pic16_freeAsmop(result,NULL,ic,TRUE);
10914     
10915         
10916 }
10917
10918 #if 0
10919 /* This code is not adjusted to PIC16 and fails utterly.
10920  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10921
10922 /*-----------------------------------------------------------------*/
10923 /* genFarPointerGet - gget value from far space                    */
10924 /*-----------------------------------------------------------------*/
10925 static void genFarPointerGet (operand *left,
10926                               operand *result, iCode *ic)
10927 {
10928     int size, offset ;
10929     sym_link *retype = getSpec(operandType(result));
10930
10931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10932
10933     pic16_aopOp(left,ic,FALSE);
10934
10935     /* if the operand is already in dptr 
10936     then we do nothing else we move the value to dptr */
10937     if (AOP_TYPE(left) != AOP_STR) {
10938         /* if this is remateriazable */
10939         if (AOP_TYPE(left) == AOP_IMMD)
10940             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10941         else { /* we need to get it byte by byte */
10942             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10943             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10944             if (options.model == MODEL_FLAT24)
10945             {
10946                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10947             }
10948         }
10949     }
10950     /* so dptr know contains the address */
10951     pic16_freeAsmop(left,NULL,ic,TRUE);
10952     pic16_aopOp(result,ic,TRUE);
10953
10954     /* if bit then unpack */
10955     if (IS_BITFIELD(retype)) 
10956         genUnpackBits(result,left,"dptr",FPOINTER);
10957     else {
10958         size = AOP_SIZE(result);
10959         offset = 0 ;
10960
10961         while (size--) {
10962             pic16_emitcode("movx","a,@dptr");
10963             pic16_aopPut(AOP(result),"a",offset++);
10964             if (size)
10965                 pic16_emitcode("inc","dptr");
10966         }
10967     }
10968
10969     pic16_freeAsmop(result,NULL,ic,TRUE);
10970 }
10971 #endif
10972
10973 #if 0
10974 /*-----------------------------------------------------------------*/
10975 /* genCodePointerGet - get value from code space                  */
10976 /*-----------------------------------------------------------------*/
10977 static void genCodePointerGet (operand *left,
10978                                 operand *result, iCode *ic)
10979 {
10980     int size, offset ;
10981     sym_link *retype = getSpec(operandType(result));
10982
10983     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10984
10985     pic16_aopOp(left,ic,FALSE);
10986
10987     /* if the operand is already in dptr 
10988     then we do nothing else we move the value to dptr */
10989     if (AOP_TYPE(left) != AOP_STR) {
10990         /* if this is remateriazable */
10991         if (AOP_TYPE(left) == AOP_IMMD)
10992             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10993         else { /* we need to get it byte by byte */
10994             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10995             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10996             if (options.model == MODEL_FLAT24)
10997             {
10998                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10999             }
11000         }
11001     }
11002     /* so dptr know contains the address */
11003     pic16_freeAsmop(left,NULL,ic,TRUE);
11004     pic16_aopOp(result,ic,FALSE);
11005
11006     /* if bit then unpack */
11007     if (IS_BITFIELD(retype)) 
11008         genUnpackBits(result,left,"dptr",CPOINTER);
11009     else {
11010         size = AOP_SIZE(result);
11011         offset = 0 ;
11012
11013         while (size--) {
11014             pic16_emitcode("clr","a");
11015             pic16_emitcode("movc","a,@a+dptr");
11016             pic16_aopPut(AOP(result),"a",offset++);
11017             if (size)
11018                 pic16_emitcode("inc","dptr");
11019         }
11020     }
11021
11022     pic16_freeAsmop(result,NULL,ic,TRUE);
11023 }
11024 #endif
11025
11026 #if 0
11027 /*-----------------------------------------------------------------*/
11028 /* genGenPointerGet - gget value from generic pointer space        */
11029 /*-----------------------------------------------------------------*/
11030 static void genGenPointerGet (operand *left,
11031                               operand *result, iCode *ic)
11032 {
11033   int size, offset, lit;
11034   sym_link *retype = getSpec(operandType(result));
11035
11036         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11037         pic16_aopOp(left,ic,FALSE);
11038         pic16_aopOp(result,ic,FALSE);
11039         size = AOP_SIZE(result);
11040
11041         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11042
11043         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11044
11045                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11046                 // load FSR0 from immediate
11047                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11048
11049 //              pic16_loadFSR0( left );
11050
11051                 offset = 0;
11052                 while(size--) {
11053                         if(size) {
11054                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11055                         } else {
11056                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11057                         }
11058                         offset++;
11059                 }
11060                 goto release;
11061
11062         }
11063         else { /* we need to get it byte by byte */
11064                 // set up FSR0 with address from left
11065                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11066                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11067                 
11068                 offset = 0 ;
11069
11070                 while(size--) {
11071                         if(size) {
11072                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11073                         } else {
11074                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11075                         }
11076                         offset++;
11077                 }
11078                 goto release;
11079         }
11080
11081   /* if bit then unpack */
11082         if (IS_BITFIELD(retype)) 
11083                 genUnpackBits(result,left,"BAD",GPOINTER);
11084
11085         release:
11086         pic16_freeAsmop(left,NULL,ic,TRUE);
11087         pic16_freeAsmop(result,NULL,ic,TRUE);
11088
11089 }
11090 #endif
11091
11092
11093 /*-----------------------------------------------------------------*/
11094 /* genGenPointerGet - gget value from generic pointer space        */
11095 /*-----------------------------------------------------------------*/
11096 static void genGenPointerGet (operand *left,
11097                               operand *result, iCode *ic)
11098 {
11099   int size, offset, lit;
11100   sym_link *letype = getSpec(operandType(left));
11101
11102     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11103     pic16_aopOp(left,ic,FALSE);
11104     pic16_aopOp(result,ic,TRUE);
11105     size = AOP_SIZE(result);
11106
11107     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11108   
11109     /* if bit then unpack */
11110     if (IS_BITFIELD(letype)) {
11111       genUnpackBits(result,left,"BAD",GPOINTER);
11112       goto release;
11113     }
11114
11115     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11116
11117       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11118       // load FSR0 from immediate
11119       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11120
11121       werror(W_POSSBUG2, __FILE__, __LINE__);
11122
11123       offset = 0;
11124       while(size--) {
11125         if(size) {
11126           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11127         } else {
11128           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11129         }
11130         offset++;
11131       }
11132
11133       goto release;
11134
11135     } else { /* we need to get it byte by byte */
11136
11137       /* set up WREG:PRODL:FSR0L with address from left */
11138       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11139       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11140       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11141       
11142       pic16_callGenericPointerRW(0, size);
11143       
11144       assignResultValue(result, 1);
11145       
11146       goto release;
11147     }
11148
11149 release:
11150   pic16_freeAsmop(left,NULL,ic,TRUE);
11151   pic16_freeAsmop(result,NULL,ic,TRUE);
11152 }
11153
11154 /*-----------------------------------------------------------------*/
11155 /* genConstPointerGet - get value from const generic pointer space */
11156 /*-----------------------------------------------------------------*/
11157 static void genConstPointerGet (operand *left,
11158                                 operand *result, iCode *ic)
11159 {
11160   //sym_link *retype = getSpec(operandType(result));
11161   // symbol *albl = newiTempLabel(NULL);        // patch 15
11162   // symbol *blbl = newiTempLabel(NULL);        //
11163   // PIC_OPCODE poc;                            // patch 15
11164   int size;
11165   int offset = 0;
11166
11167   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11168   pic16_aopOp(left,ic,FALSE);
11169   pic16_aopOp(result,ic,TRUE);
11170   size = AOP_SIZE(result);
11171
11172   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11173
11174   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11175
11176   // set up table pointer
11177   if( (AOP_TYPE(left) == AOP_PCODE) 
11178       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11179           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11180     {
11181       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11182       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11183       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11184       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11185       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11186       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11187   } else {
11188     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11189     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11190     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11191   }
11192
11193   while(size--) {
11194     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11195     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11196     offset++;
11197   }
11198     
11199   pic16_freeAsmop(left,NULL,ic,TRUE);
11200   pic16_freeAsmop(result,NULL,ic,TRUE);
11201 }
11202
11203
11204 /*-----------------------------------------------------------------*/
11205 /* genPointerGet - generate code for pointer get                   */
11206 /*-----------------------------------------------------------------*/
11207 static void genPointerGet (iCode *ic)
11208 {
11209   operand *left, *result ;
11210   sym_link *type, *etype;
11211   int p_type;
11212
11213     FENTRY;
11214     
11215     left = IC_LEFT(ic);
11216     result = IC_RESULT(ic) ;
11217
11218     /* depending on the type of pointer we need to
11219     move it to the correct pointer register */
11220     type = operandType(left);
11221     etype = getSpec(type);
11222
11223 #if 0
11224     if (IS_PTR_CONST(type))
11225 #else
11226     if (IS_CODEPTR(type))
11227 #endif
11228       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11229
11230     /* if left is of type of pointer then it is simple */
11231     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11232       p_type = DCL_TYPE(type);
11233     else {
11234       /* we have to go by the storage class */
11235       p_type = PTR_TYPE(SPEC_OCLS(etype));
11236
11237       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11238
11239       if (SPEC_OCLS(etype)->codesp ) {
11240         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11241         //p_type = CPOINTER ;   
11242       } else
11243       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11244         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11245         /*p_type = FPOINTER ;*/ 
11246       } else
11247       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11248         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11249         /* p_type = PPOINTER; */
11250       } else
11251       if (SPEC_OCLS(etype) == idata ) {
11252         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11253         /* p_type = IPOINTER; */
11254       } else {
11255         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11256         /* p_type = POINTER ; */
11257       }
11258     }
11259
11260     /* now that we have the pointer type we assign
11261     the pointer values */
11262     switch (p_type) {
11263       case POINTER:     
11264       case FPOINTER:
11265       case IPOINTER:
11266         genNearPointerGet (left,result,ic);
11267         break;
11268
11269       case PPOINTER:
11270         genPagedPointerGet(left,result,ic);
11271         break;
11272
11273 #if 0
11274       /* PICs do not support FAR pointers... */
11275       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11276       case FPOINTER:
11277         genFarPointerGet (left,result,ic);
11278         break;
11279 #endif
11280
11281       case CPOINTER:
11282         genConstPointerGet (left,result,ic);
11283         //pic16_emitcodePointerGet (left,result,ic);
11284         break;
11285
11286       case GPOINTER:
11287 #if 0
11288       if (IS_PTR_CONST(type))
11289         genConstPointerGet (left,result,ic);
11290       else
11291 #endif
11292         genGenPointerGet (left,result,ic);
11293       break;
11294
11295     default:
11296       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11297               "genPointerGet: illegal pointer type");
11298     
11299     }
11300 }
11301
11302 /*-----------------------------------------------------------------*/
11303 /* genPackBits - generates code for packed bit storage             */
11304 /*-----------------------------------------------------------------*/
11305 static void genPackBits (sym_link    *etype , operand *result,
11306                          operand *right ,
11307                          char *rname, int p_type)
11308 {
11309   int shCnt = 0 ;
11310   int offset = 0  ;
11311   int rLen = 0 ;
11312   int blen, bstr ;   
11313   sym_link *retype;
11314
11315   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11316   blen = SPEC_BLEN(etype);
11317   bstr = SPEC_BSTR(etype);
11318
11319   retype = getSpec(operandType(right));
11320
11321   if(AOP_TYPE(right) == AOP_LIT) {
11322     if((blen == 1) && (bstr < 8)) {
11323       unsigned long lit;
11324       /* it is a single bit, so use the appropriate bit instructions */
11325
11326       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11327
11328       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11329       //                        pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11330       if(!IS_PTR(operandType(result))) {
11331         /* workaround to reduce the extra lfsr instruction */
11332         if(lit) {
11333           pic16_emitpcode(POC_BSF,
11334               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11335         } else {
11336           pic16_emitpcode(POC_BCF,
11337               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11338         }
11339       } else {
11340         if (PIC_IS_DATA_PTR(operandType(result))) {
11341           pic16_loadFSR0(result, 0);
11342           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11343               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11344         } else {
11345           /* get old value */
11346           pic16_derefPtr (result, p_type, 0, NULL);
11347           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11348               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11349           /* write back new value */
11350           pic16_derefPtr (result, p_type, 1, NULL);
11351         }
11352       }
11353
11354       return;
11355     }
11356     /* move literal to W */
11357     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11358     offset++;
11359   } else
11360     if(IS_BITFIELD(retype) 
11361         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11362         && (blen == 1)) {
11363       int rblen, rbstr;
11364
11365       rblen = SPEC_BLEN( retype );
11366       rbstr = SPEC_BSTR( retype );
11367
11368
11369       if(IS_BITFIELD(etype)) {
11370         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11371         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11372       } else {
11373         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11374       }
11375
11376       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11377
11378       if(IS_BITFIELD(etype)) {
11379         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11380       } else {
11381         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11382       }
11383
11384       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11385
11386       return;
11387     } else {
11388       /* move right to W */
11389       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11390     }
11391
11392   /* if the bit length is less than or   */
11393   /* it exactly fits a byte then         */
11394   if((shCnt=SPEC_BSTR(etype))
11395       || SPEC_BLEN(etype) <= 8 )  {
11396     int fsr0_setup = 0;
11397
11398     if (blen != 8 || bstr != 0) {
11399       // we need to combine the value with the old value
11400       pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11401
11402       DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11403           SPEC_BSTR(etype), SPEC_BLEN(etype));
11404
11405       /* shift left acc */
11406       AccLsh(shCnt);
11407
11408       /* using PRODH as a temporary register here */
11409       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11410
11411       if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11412         /* access symbol directly */
11413         pic16_mov2w (AOP(result), 0);
11414       } else {
11415         /* get old value */
11416         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11417       }
11418 #if 1
11419       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11420             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11421                             (unsigned char)(0xff >> (8-bstr))) ));
11422       pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11423     } // if (blen != 8 || bstr != 0)
11424
11425     /* write new value back */
11426     if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11427       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11428     } else {
11429       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11430     }
11431 #endif
11432
11433     return;
11434   }
11435
11436
11437 #if 0
11438   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11439   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11440   exit(-1);
11441 #endif
11442
11443
11444   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11445   rLen = SPEC_BLEN(etype)-8;
11446
11447   /* now generate for lengths greater than one byte */
11448   while (1) {
11449     rLen -= 8 ;
11450     if (rLen <= 0 ) {
11451       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11452       break ;
11453     }
11454
11455     switch (p_type) {
11456       case POINTER:
11457         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11458         break;
11459
11460         /*
11461            case FPOINTER:
11462            MOVA(l);
11463            pic16_emitcode("movx","@dptr,a");
11464            break;
11465
11466            case GPOINTER:
11467            MOVA(l);
11468            DEBUGpic16_emitcode(";lcall","__gptrput");
11469            break;  
11470          */
11471       default:
11472         assert(0);
11473     }   
11474
11475
11476     pic16_mov2w(AOP(right), offset++);
11477   }
11478
11479   /* last last was not complete */
11480   if (rLen)   {
11481     /* save the byte & read byte */
11482     switch (p_type) {
11483       case POINTER:
11484         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11485         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11486         break;
11487
11488         /*
11489            case FPOINTER:
11490            pic16_emitcode ("mov","b,a");
11491            pic16_emitcode("movx","a,@dptr");
11492            break;
11493
11494            case GPOINTER:
11495            pic16_emitcode ("push","b");
11496            pic16_emitcode ("push","acc");
11497            pic16_emitcode ("lcall","__gptrget");
11498            pic16_emitcode ("pop","b");
11499            break;
11500          */
11501       default:
11502         assert(0);
11503     }
11504     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11505     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11506     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11507     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11508     //        pic16_emitcode ("orl","a,b");
11509   }
11510
11511   //    if (p_type == GPOINTER)
11512   //        pic16_emitcode("pop","b");
11513
11514   switch (p_type) {
11515
11516     case POINTER:
11517       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11518       //        pic16_emitcode("mov","@%s,a",rname);
11519       break;
11520       /*
11521          case FPOINTER:
11522          pic16_emitcode("movx","@dptr,a");
11523          break;
11524
11525          case GPOINTER:
11526          DEBUGpic16_emitcode(";lcall","__gptrput");
11527          break;                 
11528        */
11529     default:
11530       assert(0);
11531   }
11532
11533   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11534 }
11535
11536 /*-----------------------------------------------------------------*/
11537 /* genDataPointerSet - remat pointer to data space                 */
11538 /*-----------------------------------------------------------------*/
11539 static void genDataPointerSet(operand *right,
11540                               operand *result,
11541                               iCode *ic)
11542 {
11543     int size, offset = 0, resoffset=0 ;
11544
11545     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11546     pic16_aopOp(right,ic,FALSE);
11547
11548     size = AOP_SIZE(right);
11549
11550 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11551
11552 #if 0
11553     if ( AOP_TYPE(result) == AOP_PCODE) {
11554       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11555               AOP(result)->aopu.pcop->name,
11556                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11557               PCOR(AOP(result)->aopu.pcop)->instance:
11558               PCOI(AOP(result)->aopu.pcop)->offset);
11559     }
11560 #endif
11561
11562         if(AOP(result)->aopu.pcop->type == PO_DIR)
11563                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11564
11565         while (size--) {
11566                 if (AOP_TYPE(right) == AOP_LIT) {
11567                   unsigned int lit;
11568
11569                     if(!IS_FLOAT(operandType( right )))
11570                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11571                     else {
11572                       union {
11573                         unsigned long lit_int;
11574                         float lit_float;
11575                       } info;
11576         
11577                         /* take care if literal is a float */
11578                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11579                         lit = info.lit_int;
11580                     }
11581
11582                     lit = lit >> (8*offset);
11583                     if(lit&0xff) {
11584                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11585                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11586                     } else {
11587                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11588                     }
11589                 } else {
11590                   pic16_mov2w(AOP(right), offset);
11591                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11592                 }
11593                 offset++;
11594                 resoffset++;
11595         }
11596
11597     pic16_freeAsmop(right,NULL,ic,TRUE);
11598 }
11599
11600
11601
11602 /*-----------------------------------------------------------------*/
11603 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11604 /*-----------------------------------------------------------------*/
11605 static void genNearPointerSet (operand *right,
11606                                operand *result, 
11607                                iCode *ic)
11608 {
11609   asmop *aop = NULL;
11610   sym_link *retype;
11611   sym_link *ptype = operandType(result);
11612   sym_link *resetype;
11613     
11614         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11615         retype= getSpec(operandType(right));
11616         resetype = getSpec(operandType(result));
11617   
11618         pic16_aopOp(result,ic,FALSE);
11619     
11620         /* if the result is rematerializable &
11621          * in data space & not a bit variable */
11622         
11623         /* and result is not a bit variable */
11624         if (AOP_TYPE(result) == AOP_PCODE
11625 //              && AOP_TYPE(result) == AOP_IMMD
11626                 && DCL_TYPE(ptype) == POINTER
11627                 && !IS_BITFIELD(retype)
11628                 && !IS_BITFIELD(resetype)) {
11629
11630                 genDataPointerSet (right,result,ic);
11631                 pic16_freeAsmop(result,NULL,ic,TRUE);
11632           return;
11633         }
11634
11635         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11636         pic16_aopOp(right,ic,FALSE);
11637         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11638
11639         /* if bitfield then unpack the bits */
11640         if (IS_BITFIELD(resetype)) {
11641                 genPackBits (resetype, result, right, NULL, POINTER);
11642         } else {
11643                 /* we have can just get the values */
11644           int size = AOP_SIZE(right);
11645           int offset = 0 ;    
11646
11647             pic16_loadFSR0(result, 0);
11648             
11649                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11650                 while (size--) {
11651                                 if (AOP_TYPE(right) == AOP_LIT) {
11652                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11653                                         if (size) {
11654                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11655                                         } else {
11656                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11657                                         }
11658                                 } else { // no literal
11659                                         if(size) {
11660                                                 pic16_emitpcode(POC_MOVFF,
11661                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11662                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11663                                         } else {
11664                                                 pic16_emitpcode(POC_MOVFF,
11665                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11666                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11667                                         }
11668                                 }
11669                         offset++;
11670                 }
11671         }
11672
11673         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11674         /* now some housekeeping stuff */
11675         if (aop) {
11676           /* we had to allocate for this iCode */
11677           pic16_freeAsmop(NULL,aop,ic,TRUE);
11678         } else { 
11679           /* we did not allocate which means left
11680            * already in a pointer register, then
11681            * if size > 0 && this could be used again
11682            * we have to point it back to where it 
11683            * belongs */
11684           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11685           if (AOP_SIZE(right) > 1
11686             && !OP_SYMBOL(result)->remat
11687             && ( OP_SYMBOL(result)->liveTo > ic->seq
11688             || ic->depth )) {
11689
11690               int size = AOP_SIZE(right) - 1;
11691
11692                 while (size--)
11693                   pic16_emitcode("decf","fsr0,f");
11694                   //pic16_emitcode("dec","%s",rname);
11695             }
11696         }
11697
11698     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11699     /* done */
11700 //release:
11701     pic16_freeAsmop(right,NULL,ic,TRUE);
11702     pic16_freeAsmop(result,NULL,ic,TRUE);
11703 }
11704
11705 /*-----------------------------------------------------------------*/
11706 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11707 /*-----------------------------------------------------------------*/
11708 static void genPagedPointerSet (operand *right,
11709                                operand *result, 
11710                                iCode *ic)
11711 {
11712     asmop *aop = NULL;
11713     regs *preg = NULL ;
11714     char *rname , *l;
11715     sym_link *retype;
11716        
11717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11718
11719     retype= getSpec(operandType(right));
11720     
11721     pic16_aopOp(result,ic,FALSE);
11722     
11723     /* if the value is already in a pointer register
11724        then don't need anything more */
11725     if (!AOP_INPREG(AOP(result))) {
11726         /* otherwise get a free pointer register */
11727         aop = newAsmop(0);
11728         preg = getFreePtr(ic,&aop,FALSE);
11729         pic16_emitcode("mov","%s,%s",
11730                 preg->name,
11731                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11732         rname = preg->name ;
11733     } else
11734         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11735     
11736     pic16_freeAsmop(result,NULL,ic,TRUE);
11737     pic16_aopOp (right,ic,FALSE);
11738
11739     /* if bitfield then unpack the bits */
11740     if (IS_BITFIELD(retype)) 
11741         genPackBits (retype,result,right,rname,PPOINTER);
11742     else {
11743         /* we have can just get the values */
11744         int size = AOP_SIZE(right);
11745         int offset = 0 ;        
11746         
11747         while (size--) {
11748             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11749             
11750             MOVA(l);
11751             pic16_emitcode("movx","@%s,a",rname);
11752
11753             if (size)
11754                 pic16_emitcode("inc","%s",rname);
11755
11756             offset++;
11757         }
11758     }
11759     
11760     /* now some housekeeping stuff */
11761     if (aop) {
11762         /* we had to allocate for this iCode */
11763         pic16_freeAsmop(NULL,aop,ic,TRUE);
11764     } else { 
11765         /* we did not allocate which means left
11766            already in a pointer register, then
11767            if size > 0 && this could be used again
11768            we have to point it back to where it 
11769            belongs */
11770         if (AOP_SIZE(right) > 1 &&
11771             !OP_SYMBOL(result)->remat &&
11772             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11773               ic->depth )) {
11774             int size = AOP_SIZE(right) - 1;
11775             while (size--)
11776                 pic16_emitcode("dec","%s",rname);
11777         }
11778     }
11779
11780     /* done */
11781     pic16_freeAsmop(right,NULL,ic,TRUE);
11782     
11783         
11784 }
11785
11786 #if 0
11787 /* This code is not adjusted to PIC16 and fails utterly...
11788  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11789
11790 /*-----------------------------------------------------------------*/
11791 /* genFarPointerSet - set value from far space                     */
11792 /*-----------------------------------------------------------------*/
11793 static void genFarPointerSet (operand *right,
11794                               operand *result, iCode *ic)
11795 {
11796     int size, offset ;
11797     sym_link *retype = getSpec(operandType(right));
11798
11799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11800     pic16_aopOp(result,ic,FALSE);
11801
11802     /* if the operand is already in dptr 
11803     then we do nothing else we move the value to dptr */
11804     if (AOP_TYPE(result) != AOP_STR) {
11805         /* if this is remateriazable */
11806         if (AOP_TYPE(result) == AOP_IMMD)
11807             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11808         else { /* we need to get it byte by byte */
11809             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11810             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11811             if (options.model == MODEL_FLAT24)
11812             {
11813                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11814             }
11815         }
11816     }
11817     /* so dptr know contains the address */
11818     pic16_freeAsmop(result,NULL,ic,TRUE);
11819     pic16_aopOp(right,ic,FALSE);
11820
11821     /* if bit then unpack */
11822     if (IS_BITFIELD(retype)) 
11823         genPackBits(retype,result,right,"dptr",FPOINTER);
11824     else {
11825         size = AOP_SIZE(right);
11826         offset = 0 ;
11827
11828         while (size--) {
11829             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11830             MOVA(l);
11831             pic16_emitcode("movx","@dptr,a");
11832             if (size)
11833                 pic16_emitcode("inc","dptr");
11834         }
11835     }
11836
11837     pic16_freeAsmop(right,NULL,ic,TRUE);
11838 }
11839 #endif
11840
11841 /*-----------------------------------------------------------------*/
11842 /* genGenPointerSet - set value from generic pointer space         */
11843 /*-----------------------------------------------------------------*/
11844 #if 0
11845 static void genGenPointerSet (operand *right,
11846                               operand *result, iCode *ic)
11847 {
11848         int i, size, offset, lit;
11849         sym_link *retype = getSpec(operandType(right));
11850
11851         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11852
11853         pic16_aopOp(result,ic,FALSE);
11854         pic16_aopOp(right,ic,FALSE);
11855         size = AOP_SIZE(right);
11856         offset = 0;
11857
11858         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11859
11860         /* if the operand is already in dptr 
11861                 then we do nothing else we move the value to dptr */
11862         if (AOP_TYPE(result) != AOP_STR) {
11863                 /* if this is remateriazable */
11864                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11865                 // WARNING: anythig until "else" is untested!
11866                 if (AOP_TYPE(result) == AOP_IMMD) {
11867                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11868                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11869                         // load FSR0 from immediate
11870                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11871                         offset = 0;
11872                         while(size--) {
11873                                 if(size) {
11874                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11875                                 } else {
11876                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11877                                 }
11878                                 offset++;
11879                         }
11880                         goto release;
11881                 }
11882                 else { /* we need to get it byte by byte */
11883                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11884                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11885
11886                         // set up FSR0 with address of result
11887                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11888                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11889
11890                         /* hack hack! see if this the FSR. If so don't load W */
11891                         if(AOP_TYPE(right) != AOP_ACC) {
11892
11893                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11894
11895                                 if(AOP_TYPE(right) == AOP_LIT)
11896                                 {
11897                                         // copy literal
11898                                         // note: pic16_popGet handles sign extension
11899                                         for(i=0;i<size;i++) {
11900                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11901                                                 if(i < size-1)
11902                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11903                                                 else
11904                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11905                                         }
11906                                 } else {
11907                                         // copy regs
11908
11909                                         for(i=0;i<size;i++) {
11910                                                 if(i < size-1)
11911                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11912                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11913                                                 else
11914                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11915                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11916                                         }
11917                                 }
11918                                 goto release;
11919                         } 
11920                         // right = ACC
11921                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11922                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11923                         goto release;
11924         } // if (AOP_TYPE(result) != AOP_IMMD)
11925
11926         } // if (AOP_TYPE(result) != AOP_STR)
11927         /* so dptr know contains the address */
11928
11929
11930         /* if bit then unpack */
11931         if (IS_BITFIELD(retype)) 
11932                 genPackBits(retype,result,right,"dptr",GPOINTER);
11933         else {
11934                 size = AOP_SIZE(right);
11935                 offset = 0 ;
11936
11937                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11938
11939                 // set up FSR0 with address of result
11940                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11941                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11942         
11943                 while (size--) {
11944                         if (AOP_TYPE(right) == AOP_LIT) {
11945                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11946                                 if (size) {
11947                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11948                                 } else {
11949                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11950                                 }
11951                         } else { // no literal
11952                                 if(size) {
11953                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11954                                 } else {
11955                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11956                                 }
11957                         }
11958                         offset++;
11959                 }
11960         }
11961
11962         release:
11963         pic16_freeAsmop(right,NULL,ic,TRUE);
11964         pic16_freeAsmop(result,NULL,ic,TRUE);
11965 }
11966 #endif
11967
11968 static void genGenPointerSet (operand *right,
11969                               operand *result, iCode *ic)
11970 {
11971   int size;
11972   sym_link *retype = getSpec(operandType(result));
11973
11974     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11975
11976     pic16_aopOp(result,ic,FALSE);
11977     pic16_aopOp(right,ic,FALSE);
11978     size = AOP_SIZE(right);
11979
11980     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11981
11982
11983     /* if bit then unpack */
11984     if (IS_BITFIELD(retype)) {
11985 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11986       genPackBits(retype,result,right,"dptr",GPOINTER);
11987       goto release;
11988     }
11989
11990     size = AOP_SIZE(right);
11991
11992     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11993
11994
11995     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11996
11997     /* value of right+0 is placed on stack, which will be retrieved
11998      * by the support function this restoring the stack. The important
11999      * thing is that there is no need to manually restore stack pointer
12000      * here */
12001     pushaop(AOP(right), 0);
12002 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12003     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12004     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12005     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12006     
12007     /* load address to write to in WREG:FSR0H:FSR0L */
12008     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12009                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12010     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12011                                 pic16_popCopyReg(&pic16_pc_prodl)));
12012     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12013     
12014     pic16_callGenericPointerRW(1, size);
12015
12016 release:
12017     pic16_freeAsmop(right,NULL,ic,TRUE);
12018     pic16_freeAsmop(result,NULL,ic,TRUE);
12019 }
12020
12021 /*-----------------------------------------------------------------*/
12022 /* genPointerSet - stores the value into a pointer location        */
12023 /*-----------------------------------------------------------------*/
12024 static void genPointerSet (iCode *ic)
12025 {    
12026   operand *right, *result ;
12027   sym_link *type, *etype;
12028   int p_type;
12029
12030     FENTRY;
12031
12032     right = IC_RIGHT(ic);
12033     result = IC_RESULT(ic) ;
12034
12035     /* depending on the type of pointer we need to
12036     move it to the correct pointer register */
12037     type = operandType(result);
12038     etype = getSpec(type);
12039     
12040     /* if left is of type of pointer then it is simple */
12041     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12042         p_type = DCL_TYPE(type);
12043     }
12044     else {
12045         /* we have to go by the storage class */
12046         p_type = PTR_TYPE(SPEC_OCLS(etype));
12047
12048 /*      if (SPEC_OCLS(etype)->codesp ) { */
12049 /*          p_type = CPOINTER ;  */
12050 /*      } */
12051 /*      else */
12052 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12053 /*              p_type = FPOINTER ; */
12054 /*          else */
12055 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12056 /*                  p_type = PPOINTER ; */
12057 /*              else */
12058 /*                  if (SPEC_OCLS(etype) == idata ) */
12059 /*                      p_type = IPOINTER ; */
12060 /*                  else */
12061 /*                      p_type = POINTER ; */
12062     }
12063
12064     /* now that we have the pointer type we assign
12065     the pointer values */
12066     switch (p_type) {
12067       case POINTER:
12068       case FPOINTER:
12069       case IPOINTER:
12070         genNearPointerSet (right,result,ic);
12071         break;
12072
12073       case PPOINTER:
12074         genPagedPointerSet (right,result,ic);
12075         break;
12076
12077 #if 0
12078       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12079       case FPOINTER:
12080         genFarPointerSet (right,result,ic);
12081         break;
12082 #endif
12083         
12084       case GPOINTER:
12085         genGenPointerSet (right,result,ic);
12086         break;
12087
12088       default:
12089         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12090           "genPointerSet: illegal pointer type");
12091     }
12092 }
12093
12094 /*-----------------------------------------------------------------*/
12095 /* genIfx - generate code for Ifx statement                        */
12096 /*-----------------------------------------------------------------*/
12097 static void genIfx (iCode *ic, iCode *popIc)
12098 {
12099   operand *cond = IC_COND(ic);
12100   int isbit =0;
12101
12102     FENTRY;
12103
12104     pic16_aopOp(cond,ic,FALSE);
12105
12106     /* get the value into acc */
12107     if (AOP_TYPE(cond) != AOP_CRY)
12108       pic16_toBoolean(cond);
12109     else
12110       isbit = 1;
12111     /* the result is now in the accumulator */
12112     pic16_freeAsmop(cond,NULL,ic,TRUE);
12113
12114     /* if there was something to be popped then do it */
12115     if (popIc)
12116       genIpop(popIc);
12117
12118     /* if the condition is  a bit variable */
12119     if (isbit && IS_ITEMP(cond) && 
12120         SPIL_LOC(cond)) {
12121       genIfxJump(ic,"c");
12122       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12123     } else {
12124       if (isbit && !IS_ITEMP(cond))
12125         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12126         else
12127         genIfxJump(ic,"a");
12128     }
12129     ic->generated = 1;
12130 }
12131
12132 /*-----------------------------------------------------------------*/
12133 /* genAddrOf - generates code for address of                       */
12134 /*-----------------------------------------------------------------*/
12135 static void genAddrOf (iCode *ic)
12136 {
12137   operand *result, *left;
12138   int size;
12139   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12140   pCodeOp *pcop0, *pcop1, *pcop2;
12141
12142     FENTRY;
12143
12144     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12145
12146     sym = OP_SYMBOL( IC_LEFT(ic) );
12147     
12148     if(sym->onStack) {
12149       /* get address of symbol on stack */
12150       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12151 #if 0
12152       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12153                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12154 #endif
12155
12156       // operands on stack are accessible via "FSR2 + index" with index
12157       // starting at 2 for arguments and growing from 0 downwards for
12158       // local variables (index == 0 is not assigned so we add one here)
12159       {
12160         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12161         if (soffs <= 0) {
12162           assert (soffs < 0);
12163           soffs++;
12164         } // if
12165         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12166         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12167         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12168         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12169         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12170         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12171         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12172       }
12173
12174       goto release;
12175     }
12176         
12177 //      if(pic16_debug_verbose) {
12178 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12179 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12180 //      }
12181         
12182     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12183     size = AOP_SIZE(IC_RESULT(ic));
12184
12185     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12186     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12187     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12188         
12189     if (size == 3) {
12190       pic16_emitpcode(POC_MOVLW, pcop0);
12191       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12192       pic16_emitpcode(POC_MOVLW, pcop1);
12193       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12194       pic16_emitpcode(POC_MOVLW, pcop2);
12195       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12196     } else
12197     if (size == 2) {
12198       pic16_emitpcode(POC_MOVLW, pcop0);
12199       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12200       pic16_emitpcode(POC_MOVLW, pcop1);
12201     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12202     } else {
12203       pic16_emitpcode(POC_MOVLW, pcop0);
12204       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12205     }
12206
12207     pic16_freeAsmop(left, NULL, ic, FALSE);
12208 release:
12209     pic16_freeAsmop(result,NULL,ic,TRUE);
12210 }
12211
12212
12213 #if 0
12214 /*-----------------------------------------------------------------*/
12215 /* genFarFarAssign - assignment when both are in far space         */
12216 /*-----------------------------------------------------------------*/
12217 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12218 {
12219     int size = AOP_SIZE(right);
12220     int offset = 0;
12221     char *l ;
12222     /* first push the right side on to the stack */
12223     while (size--) {
12224         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12225         MOVA(l);
12226         pic16_emitcode ("push","acc");
12227     }
12228     
12229     pic16_freeAsmop(right,NULL,ic,FALSE);
12230     /* now assign DPTR to result */
12231     pic16_aopOp(result,ic,FALSE);
12232     size = AOP_SIZE(result);
12233     while (size--) {
12234         pic16_emitcode ("pop","acc");
12235         pic16_aopPut(AOP(result),"a",--offset);
12236     }
12237     pic16_freeAsmop(result,NULL,ic,FALSE);
12238         
12239 }
12240 #endif
12241
12242 /*-----------------------------------------------------------------*/
12243 /* genAssign - generate code for assignment                        */
12244 /*-----------------------------------------------------------------*/
12245 static void genAssign (iCode *ic)
12246 {
12247   operand *result, *right;
12248   int size, offset,know_W;
12249   unsigned long lit = 0L;
12250
12251   result = IC_RESULT(ic);
12252   right  = IC_RIGHT(ic) ;
12253
12254   FENTRY;
12255   
12256   /* if they are the same */
12257   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12258     return ;
12259
12260   /* reversed order operands are aopOp'ed so that result operand
12261    * is effective in case right is a stack symbol. This maneauver
12262    * allows to use the _G.resDirect flag later */
12263   pic16_aopOp(result,ic,TRUE);
12264   pic16_aopOp(right,ic,FALSE);
12265
12266   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12267
12268   /* if they are the same registers */
12269   if (pic16_sameRegs(AOP(right),AOP(result)))
12270     goto release;
12271
12272   /* if the result is a bit */
12273   if (AOP_TYPE(result) == AOP_CRY) {
12274     /* if the right size is a literal then
12275        we know what the value is */
12276     if (AOP_TYPE(right) == AOP_LIT) {
12277           
12278       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12279                   pic16_popGet(AOP(result),0));
12280
12281       if (((int) operandLitValue(right))) 
12282         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12283                        AOP(result)->aopu.aop_dir,
12284                        AOP(result)->aopu.aop_dir);
12285       else
12286         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12287                        AOP(result)->aopu.aop_dir,
12288                        AOP(result)->aopu.aop_dir);
12289       goto release;
12290     }
12291
12292     /* the right is also a bit variable */
12293     if (AOP_TYPE(right) == AOP_CRY) {
12294       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12295       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12296       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12297
12298       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12299                      AOP(result)->aopu.aop_dir,
12300                      AOP(result)->aopu.aop_dir);
12301       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12302                      AOP(right)->aopu.aop_dir,
12303                      AOP(right)->aopu.aop_dir);
12304       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12305                      AOP(result)->aopu.aop_dir,
12306                      AOP(result)->aopu.aop_dir);
12307       goto release ;
12308     }
12309
12310     /* we need to or */
12311     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12312     pic16_toBoolean(right);
12313     emitSKPZ;
12314     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12315     //pic16_aopPut(AOP(result),"a",0);
12316     goto release ;
12317   }
12318
12319   /* bit variables done */
12320   /* general case */
12321   size = AOP_SIZE(result);
12322   offset = 0 ;
12323
12324   if(AOP_TYPE(right) == AOP_LIT) {
12325         if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12326                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12327         else{
12328            union {
12329               unsigned long lit_int;
12330               float lit_float;
12331             } info;
12332         
12333
12334               if(IS_FIXED16X16(operandType(right))) {
12335                 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12336               } else {
12337                 /* take care if literal is a float */
12338                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12339                 lit = info.lit_int;
12340               }
12341         }
12342   }
12343
12344 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12345 //                      sizeof(unsigned long int), sizeof(float));
12346
12347
12348   if (AOP_TYPE(right) == AOP_REG) {
12349     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12350     while (size--) {
12351       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12352     } // while
12353     goto release;
12354   }
12355
12356   /* when do we have to read the program memory?
12357    * - if right itself is a symbol in code space
12358    *   (we don't care what it points to if it's a pointer)
12359    * - AND right is not a function (we would want its address)
12360    */
12361   if(AOP_TYPE(right) != AOP_LIT
12362         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12363         && !IS_FUNC(OP_SYM_TYPE(right))
12364         && !IS_ITEMP(right))
12365   {
12366         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12367         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12368
12369         // set up table pointer
12370         if(is_LitOp(right)) {
12371 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12372                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12373                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12374                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12375                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12376                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12377                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12378         } else {
12379 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12380                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12381                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12382                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12383                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12384                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12385                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12386         }
12387
12388         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12389         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12390         while(size--) {
12391                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12392                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12393                         pic16_popGet(AOP(result),offset)));
12394                 offset++;
12395         }
12396
12397         /* FIXME: for pointers we need to extend differently (according
12398          * to pointer type DATA/CODE/EEPROM/... :*/
12399         size = getSize(OP_SYM_TYPE(right));
12400         if(AOP_SIZE(result) > size) {
12401                 size = AOP_SIZE(result) - size;
12402                 while(size--) {
12403                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12404                         offset++;
12405                 }
12406         }
12407         goto release;
12408   }
12409
12410   if (AOP_TYPE(right) == AOP_LIT && IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
12411   {
12412     /* Arrg -- a literal is cast into a generic pointer: how shall we decide which TAG
12413      *         to assign (__data, __code, __eeprom, ???)??? */
12414     fprintf (stderr, "%s:%u(%s): creating generic pointer from literal defaults to __data TYPE*.\n\tPlease explicitly cast to (__data|__code) TYPE* in line %u if neccessary!\n",
12415         __FILE__, __LINE__, __FUNCTION__, ic->lineno);
12416     /* assume __data space */
12417     lit = (lit & 0x00ffff) | 0x800000;
12418     //exit (-1);
12419   }
12420
12421
12422 #if 0
12423 /* VR - What is this?! */
12424   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12426     if(aopIdx(AOP(result),0) == 4) {
12427
12428       /* this is a workaround to save value of right into wreg too,
12429        * value of wreg is going to be used later */
12430       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12431       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12432       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12433       goto release;
12434     } else
12435 //      assert(0);
12436       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12437   }
12438 #endif
12439
12440   know_W=-1;
12441   while (size--) {
12442   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12443     if(AOP_TYPE(right) == AOP_LIT) {
12444       if(lit&0xff) {
12445         if(know_W != (lit&0xff))
12446           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12447         know_W = lit&0xff;
12448         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12449       } else
12450         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12451
12452       lit >>= 8;
12453
12454     } else if (AOP_TYPE(right) == AOP_CRY) {
12455       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12456       if(offset == 0) {
12457         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12458         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12459         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12460       }
12461     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12462         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12463         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12464     } else {
12465       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12466
12467       if(!_G.resDirect)         /* use this aopForSym feature */
12468         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12469     }
12470             
12471     offset++;
12472   }
12473   
12474  release:
12475   pic16_freeAsmop (right,NULL,ic,FALSE);
12476   pic16_freeAsmop (result,NULL,ic,TRUE);
12477 }   
12478
12479 /*-----------------------------------------------------------------*/
12480 /* genJumpTab - generates code for jump table                       */
12481 /*-----------------------------------------------------------------*/
12482 static void genJumpTab (iCode *ic)
12483 {
12484   symbol *jtab;
12485   char *l;
12486   pCodeOp *jt_offs;
12487   pCodeOp *jt_offs_hi;
12488   pCodeOp *jt_label;
12489
12490     FENTRY;
12491
12492     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12493     /* get the condition into accumulator */
12494     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12495     MOVA(l);
12496     /* multiply by three */
12497     pic16_emitcode("add","a,acc");
12498     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12499
12500     jtab = newiTempLabel(NULL);
12501     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12502     pic16_emitcode("jmp","@a+dptr");
12503     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12504
12505 #if 0
12506     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12507     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12508     emitSKPNC;
12509     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12510     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12511     pic16_emitpLabel(jtab->key);
12512
12513 #else
12514
12515     jt_offs = pic16_popGetTempReg(0);
12516     jt_offs_hi = pic16_popGetTempReg(1);
12517     jt_label = pic16_popGetLabel (jtab->key);
12518     //fprintf (stderr, "Creating jump table...\n");
12519
12520     // calculate offset into jump table (idx * sizeof (GOTO))
12521     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12522     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12523     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12524     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12525     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12526     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12527     pic16_emitpcode(POC_MOVWF , jt_offs);
12528
12529     // prepare PCLATx (set to first entry in jump table)
12530     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12531     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12532     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12533     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12534     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12535
12536     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12537     pic16_emitpcode(POC_ADDWF , jt_offs);
12538     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12539     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12540     emitSKPNC;
12541     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12542
12543     // release temporaries and prepare jump into table (new PCL --> WREG)
12544     pic16_emitpcode(POC_MOVFW , jt_offs);
12545     pic16_popReleaseTempReg (jt_offs_hi, 1);
12546     pic16_popReleaseTempReg (jt_offs, 0);
12547
12548     // jump into the table
12549     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12550
12551     pic16_emitpLabelFORCE(jtab->key);
12552 #endif
12553
12554     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12555 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12556
12557     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12558     /* now generate the jump labels */
12559     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12560          jtab = setNextItem(IC_JTLABELS(ic))) {
12561 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12562         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12563         
12564     }
12565     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12566
12567 }
12568
12569 /*-----------------------------------------------------------------*/
12570 /* genMixedOperation - gen code for operators between mixed types  */
12571 /*-----------------------------------------------------------------*/
12572 /*
12573   TSD - Written for the PIC port - but this unfortunately is buggy.
12574   This routine is good in that it is able to efficiently promote 
12575   types to different (larger) sizes. Unfortunately, the temporary
12576   variables that are optimized out by this routine are sometimes
12577   used in other places. So until I know how to really parse the 
12578   iCode tree, I'm going to not be using this routine :(.
12579 */
12580 static int genMixedOperation (iCode *ic)
12581 {
12582 #if 0
12583   operand *result = IC_RESULT(ic);
12584   sym_link *ctype = operandType(IC_LEFT(ic));
12585   operand *right = IC_RIGHT(ic);
12586   int ret = 0;
12587   int big,small;
12588   int offset;
12589
12590   iCode *nextic;
12591   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12592
12593   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12594
12595   nextic = ic->next;
12596   if(!nextic)
12597     return 0;
12598
12599   nextright = IC_RIGHT(nextic);
12600   nextleft  = IC_LEFT(nextic);
12601   nextresult = IC_RESULT(nextic);
12602
12603   pic16_aopOp(right,ic,FALSE);
12604   pic16_aopOp(result,ic,FALSE);
12605   pic16_aopOp(nextright,  nextic, FALSE);
12606   pic16_aopOp(nextleft,   nextic, FALSE);
12607   pic16_aopOp(nextresult, nextic, FALSE);
12608
12609   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12610
12611     operand *t = right;
12612     right = nextright;
12613     nextright = t; 
12614
12615     pic16_emitcode(";remove right +","");
12616
12617   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12618 /*
12619     operand *t = right;
12620     right = nextleft;
12621     nextleft = t; 
12622 */
12623     pic16_emitcode(";remove left +","");
12624   } else
12625     return 0;
12626
12627   big = AOP_SIZE(nextleft);
12628   small = AOP_SIZE(nextright);
12629
12630   switch(nextic->op) {
12631
12632   case '+':
12633     pic16_emitcode(";optimize a +","");
12634     /* if unsigned or not an integral type */
12635     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12636       pic16_emitcode(";add a bit to something","");
12637     } else {
12638
12639       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12640
12641       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12642         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12643         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12644       } else
12645         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12646
12647       offset = 0;
12648       while(--big) {
12649
12650         offset++;
12651
12652         if(--small) {
12653           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12654             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12655             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12656           }
12657
12658           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12659           emitSKPNC;
12660           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12661                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12662                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12663           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12664           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12665
12666         } else {
12667           pic16_emitcode("rlf","known_zero,w");
12668
12669           /*
12670             if right is signed
12671               btfsc  right,7
12672                addlw ff
12673           */
12674           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12675             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12676             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12677           } else {
12678             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12679           }
12680         }
12681       }
12682       ret = 1;
12683     }
12684   }
12685   ret = 1;
12686
12687 release:
12688   pic16_freeAsmop(right,NULL,ic,TRUE);
12689   pic16_freeAsmop(result,NULL,ic,TRUE);
12690   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12691   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12692   if(ret)
12693     nextic->generated = 1;
12694
12695   return ret;
12696 #else
12697   return 0;
12698 #endif
12699 }
12700 /*-----------------------------------------------------------------*/
12701 /* genCast - gen code for casting                                  */
12702 /*-----------------------------------------------------------------*/
12703 static void genCast (iCode *ic)
12704 {
12705   operand *result = IC_RESULT(ic);
12706   sym_link *ctype = operandType(IC_LEFT(ic));
12707   sym_link *rtype = operandType(IC_RIGHT(ic));
12708   sym_link *restype = operandType(IC_RESULT(ic));
12709   operand *right = IC_RIGHT(ic);
12710   int size, offset ;
12711
12712
12713     FENTRY;
12714
12715         /* if they are equivalent then do nothing */
12716 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12717 //              return ;
12718
12719         pic16_aopOp(result,ic,FALSE);
12720         pic16_aopOp(right,ic,FALSE) ;
12721
12722         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12723
12724
12725         /* if the result is a bit */
12726         if (AOP_TYPE(result) == AOP_CRY) {
12727         
12728                 /* if the right size is a literal then
12729                  * we know what the value is */
12730                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12731
12732                 if (AOP_TYPE(right) == AOP_LIT) {
12733                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12734                                 pic16_popGet(AOP(result),0));
12735
12736                         if (((int) operandLitValue(right))) 
12737                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12738                                         AOP(result)->aopu.aop_dir,
12739                                         AOP(result)->aopu.aop_dir);
12740                         else
12741                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12742                                         AOP(result)->aopu.aop_dir,
12743                                         AOP(result)->aopu.aop_dir);
12744                         goto release;
12745                 }
12746
12747                 /* the right is also a bit variable */
12748                 if (AOP_TYPE(right) == AOP_CRY) {
12749                         emitCLRC;
12750                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12751
12752                         pic16_emitcode("clrc","");
12753                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12754                                 AOP(right)->aopu.aop_dir,
12755                                 AOP(right)->aopu.aop_dir);
12756                         pic16_aopPut(AOP(result),"c",0);
12757                         goto release ;
12758                 }
12759
12760                 /* we need to or */
12761                 if (AOP_TYPE(right) == AOP_REG) {
12762                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12763                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12764                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12765                 }
12766                 pic16_toBoolean(right);
12767                 pic16_aopPut(AOP(result),"a",0);
12768                 goto release ;
12769         }
12770
12771         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12772           int offset = 1;
12773
12774                 size = AOP_SIZE(result);
12775
12776                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12777
12778                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12779                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12780                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12781
12782                 while (size--)
12783                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12784
12785                 goto release;
12786         }
12787
12788         if(IS_BITFIELD(getSpec(restype))
12789           && IS_BITFIELD(getSpec(rtype))) {
12790           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12791         }
12792         
12793         /* port from pic14 to cope with generic pointers */
12794         if (IS_PTR(restype))
12795         {
12796           operand *result = IC_RESULT(ic);
12797           //operand *left = IC_LEFT(ic);
12798           operand *right = IC_RIGHT(ic);
12799           int tag = 0xff;
12800           
12801           /* copy common part */
12802           int max, size = AOP_SIZE(result);
12803           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12804           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12805
12806           /* warn if we discard generic opinter tag */
12807           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
12808           {
12809             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
12810           } // if
12811
12812           max = size;
12813           while (size--)
12814           {
12815             pic16_mov2w (AOP(right), size);
12816             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12817           } // while
12818           pic16_addSign(result, max, 0);
12819
12820           /* upcast into generic pointer type? */
12821           if (IS_GENPTR(restype) && !IS_GENPTR(rtype))
12822           {
12823             //fprintf (stderr, "%s:%u: must determine pointer type (IS_PTR: %d, DCL_TYPE: %d)\n", __FUNCTION__, __LINE__, IS_PTR(rtype), IS_PTR(rtype) ? DCL_TYPE(rtype) : 0);
12824             if (IS_PTR(rtype))
12825             {
12826               switch (DCL_TYPE(rtype))
12827               {
12828               case POINTER:     /* __data */
12829               case FPOINTER:    /* __data */
12830                 assert (AOP_SIZE(right) == 2);
12831                 tag = 0x80;
12832                 break;
12833
12834               case CPOINTER:    /* __code */
12835                 assert (AOP_SIZE(right) == 2);
12836                 tag = 0x00;
12837                 break;
12838                 
12839               case GPOINTER:    /* unknown destination, __data or __code */
12840                 assert (AOP_SIZE(right) == 3);
12841                 /* tag taken from right operand */
12842                 break;
12843                 
12844               default:
12845                 assert (!"unhandled pointer type");
12846               } // switch
12847             } else {
12848               /* convert other values into pointers to __data space */
12849               fprintf (stderr, "%s:%u(%s): creating generic pointer from non-pointer type -- assuming __data space\n", __FILE__, __LINE__, __FUNCTION__);
12850               tag = 0x80;
12851             }
12852
12853             assert (AOP_SIZE(result) == 3);
12854             if (tag == 0) {
12855               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 2));
12856             } else {
12857               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(tag));
12858               pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), 2));
12859             }
12860           } // if
12861           goto release;
12862         }
12863
12864         /* if they are the same size : or less */
12865         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12866
12867                 /* if they are in the same place */
12868                 if (pic16_sameRegs(AOP(right),AOP(result)))
12869                         goto release;
12870
12871                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12872 #if 0
12873                 if (IS_PTR_CONST(rtype))
12874 #else
12875                 if (IS_CODEPTR(rtype))
12876 #endif
12877                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12878
12879 #if 0
12880                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12881 #else
12882                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12883 #endif
12884                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12885
12886 #if 0
12887                 if(AOP_TYPE(right) == AOP_IMMD) {
12888                   pCodeOp *pcop0, *pcop1, *pcop2;
12889                   symbol *sym = OP_SYMBOL( right );
12890
12891                         size = AOP_SIZE(result);
12892                         /* low */
12893                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12894                         /* high */
12895                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12896                         /* upper */
12897                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12898         
12899                         if (size == 3) {
12900                                 pic16_emitpcode(POC_MOVLW, pcop0);
12901                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12902                                 pic16_emitpcode(POC_MOVLW, pcop1);
12903                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12904                                 pic16_emitpcode(POC_MOVLW, pcop2);
12905                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12906                         } else
12907                         if (size == 2) {
12908                                 pic16_emitpcode(POC_MOVLW, pcop0);
12909                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12910                                 pic16_emitpcode(POC_MOVLW, pcop1);
12911                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12912                         } else {
12913                                 pic16_emitpcode(POC_MOVLW, pcop0);
12914                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12915                         }
12916                 } else
12917 #endif
12918                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12919                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12920                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12921                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12922                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12923                         if(AOP_SIZE(result) <2)
12924                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12925                 } else {
12926                         /* if they in different places then copy */
12927                         size = AOP_SIZE(result);
12928                         offset = 0 ;
12929                         while (size--) {
12930                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12931                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12932                                 offset++;
12933                         }
12934                 }
12935                 goto release;
12936         }
12937
12938         /* if the result is of type pointer */
12939         if (IS_PTR(ctype)) {
12940           int p_type;
12941           sym_link *type = operandType(right);
12942           sym_link *etype = getSpec(type);
12943
12944                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12945
12946                 /* pointer to generic pointer */
12947                 if (IS_GENPTR(ctype)) {
12948                   char *l = zero;
12949             
12950                         if (IS_PTR(type)) 
12951                                 p_type = DCL_TYPE(type);
12952                         else {
12953                 /* we have to go by the storage class */
12954                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12955
12956 /*              if (SPEC_OCLS(etype)->codesp )  */
12957 /*                  p_type = CPOINTER ;  */
12958 /*              else */
12959 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12960 /*                      p_type = FPOINTER ; */
12961 /*                  else */
12962 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12963 /*                          p_type = PPOINTER; */
12964 /*                      else */
12965 /*                          if (SPEC_OCLS(etype) == idata ) */
12966 /*                              p_type = IPOINTER ; */
12967 /*                          else */
12968 /*                              p_type = POINTER ; */
12969             }
12970                 
12971             /* the first two bytes are known */
12972       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12973             size = GPTRSIZE - 1; 
12974             offset = 0 ;
12975             while (size--) {
12976               if(offset < AOP_SIZE(right)) {
12977                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12978                 pic16_mov2f(AOP(result), AOP(right), offset);
12979 /*
12980                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12981                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12982                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12983                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12984                 } else { 
12985                   
12986                   pic16_aopPut(AOP(result),
12987                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12988                          offset);
12989                 }
12990 */
12991               } else 
12992                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12993               offset++;
12994             }
12995             /* the last byte depending on type */
12996             switch (p_type) {
12997             case IPOINTER:
12998             case POINTER:
12999                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13000                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13001 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13002                 break;
13003
13004             case CPOINTER:
13005                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13006                 break;
13007
13008             case FPOINTER:
13009               pic16_emitcode(";BUG!? ","%d",__LINE__);
13010                 l = one;
13011                 break;
13012             case PPOINTER:
13013               pic16_emitcode(";BUG!? ","%d",__LINE__);
13014                 l = "#0x03";
13015                 break;
13016
13017             case GPOINTER:
13018                 if (GPTRSIZE > AOP_SIZE(right)) {
13019                   // assume data pointer... THIS MIGHT BE WRONG!
13020                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13021                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13022                 } else {
13023                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13024                 }
13025               break;
13026               
13027             default:
13028                 /* this should never happen */
13029                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13030                        "got unknown pointer type");
13031                 exit(1);
13032             }
13033             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13034             goto release ;
13035         }
13036         
13037         
13038         assert( 0 );
13039         /* just copy the pointers */
13040         size = AOP_SIZE(result);
13041         offset = 0 ;
13042         while (size--) {
13043             pic16_aopPut(AOP(result),
13044                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13045                    offset);
13046             offset++;
13047         }
13048         goto release ;
13049     }
13050     
13051
13052
13053     /* so we now know that the size of destination is greater
13054     than the size of the source.
13055     Now, if the next iCode is an operator then we might be
13056     able to optimize the operation without performing a cast.
13057     */
13058     if(genMixedOperation(ic))
13059       goto release;
13060
13061     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13062     
13063     /* we move to result for the size of source */
13064     size = AOP_SIZE(right);
13065     offset = 0 ;
13066
13067     while (size--) {
13068       if(!_G.resDirect)
13069         pic16_mov2f(AOP(result), AOP(right), offset);
13070       offset++;
13071     }
13072
13073     /* now depending on the sign of the destination */
13074     size = AOP_SIZE(result) - AOP_SIZE(right);
13075     /* if unsigned or not an integral type */
13076     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13077       while (size--)
13078         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13079     } else {
13080       /* we need to extend the sign :( */
13081
13082       if(size == 1) {
13083         /* Save one instruction of casting char to int */
13084         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13085         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13086         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13087       } else {
13088         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13089
13090         if(offset)
13091           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13092         else
13093           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13094         
13095         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13096
13097         while (size--)
13098           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13099       }
13100     }
13101
13102 release:
13103     pic16_freeAsmop(right,NULL,ic,TRUE);
13104     pic16_freeAsmop(result,NULL,ic,TRUE);
13105
13106 }
13107
13108 /*-----------------------------------------------------------------*/
13109 /* genDjnz - generate decrement & jump if not zero instrucion      */
13110 /*-----------------------------------------------------------------*/
13111 static int genDjnz (iCode *ic, iCode *ifx)
13112 {
13113     symbol *lbl, *lbl1;
13114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13115
13116     if (!ifx)
13117         return 0;
13118     
13119     /* if the if condition has a false label
13120        then we cannot save */
13121     if (IC_FALSE(ifx))
13122         return 0;
13123
13124     /* if the minus is not of the form 
13125        a = a - 1 */
13126     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13127         !IS_OP_LITERAL(IC_RIGHT(ic)))
13128         return 0;
13129
13130     if (operandLitValue(IC_RIGHT(ic)) != 1)
13131         return 0;
13132
13133     /* if the size of this greater than one then no
13134        saving */
13135     if (getSize(operandType(IC_RESULT(ic))) > 1)
13136         return 0;
13137
13138     /* otherwise we can save BIG */
13139     lbl = newiTempLabel(NULL);
13140     lbl1= newiTempLabel(NULL);
13141
13142     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13143     
13144     if (IS_AOP_PREG(IC_RESULT(ic))) {
13145         pic16_emitcode("dec","%s",
13146                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13147         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13148         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13149     } else {    
13150
13151
13152       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13153       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13154
13155       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13156       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13157
13158     }
13159     
13160     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13161     ifx->generated = 1;
13162     return 1;
13163 }
13164
13165 /*-----------------------------------------------------------------*/
13166 /* genReceive - generate code for a receive iCode                  */
13167 /*-----------------------------------------------------------------*/
13168 static void genReceive (iCode *ic)
13169 {    
13170
13171   FENTRY;
13172
13173 #if 0
13174   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13175         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13176 #endif
13177 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13178
13179   if (isOperandInFarSpace(IC_RESULT(ic))
13180       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13181           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13182
13183     int size = getSize(operandType(IC_RESULT(ic)));
13184     int offset =  pic16_fReturnSizePic - size;
13185
13186       assert( 0 );
13187       while (size--) {
13188         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13189                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13190                       offset++;
13191         }
13192
13193       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13194
13195       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13196       size = AOP_SIZE(IC_RESULT(ic));
13197       offset = 0;
13198       while (size--) {
13199         pic16_emitcode ("pop","acc");
13200         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13201       }
13202   } else {
13203     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13204     _G.accInUse++;
13205     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13206     _G.accInUse--;
13207
13208     /* set pseudo stack pointer to where it should be - dw*/
13209     GpsuedoStkPtr = ic->parmBytes;
13210
13211     /* setting GpsuedoStkPtr has side effects here: */
13212     assignResultValue(IC_RESULT(ic), 0);
13213   }
13214
13215   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13216 }
13217
13218 /*-----------------------------------------------------------------*/
13219 /* genDummyRead - generate code for dummy read of volatiles        */
13220 /*-----------------------------------------------------------------*/
13221 static void
13222 genDummyRead (iCode * ic)
13223 {
13224   operand *op;
13225   int i;
13226
13227   op = IC_RIGHT(ic);
13228   if (op && IS_SYMOP(op)) {
13229     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13230       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13231       return;
13232     }
13233     pic16_aopOp (op, ic, FALSE);
13234     for (i=0; i < AOP_SIZE(op); i++) {
13235       // may need to protect this from the peepholer -- this is not nice but works...
13236       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13237       pic16_mov2w (AOP(op),i);
13238       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13239     } // for i
13240     pic16_freeAsmop (op, NULL, ic, TRUE);
13241   } else if (op) {
13242     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13243   } // if
13244 }
13245
13246 /*-----------------------------------------------------------------*/
13247 /* genpic16Code - generate code for pic16 based controllers        */
13248 /*-----------------------------------------------------------------*/
13249 /*
13250  * At this point, ralloc.c has gone through the iCode and attempted
13251  * to optimize in a way suitable for a PIC. Now we've got to generate
13252  * PIC instructions that correspond to the iCode.
13253  *
13254  * Once the instructions are generated, we'll pass through both the
13255  * peep hole optimizer and the pCode optimizer.
13256  *-----------------------------------------------------------------*/
13257
13258 void genpic16Code (iCode *lic)
13259 {
13260   iCode *ic;
13261   int cln = 0;
13262
13263     lineHead = lineCurr = NULL;
13264
13265     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13266     pic16_addpBlock(pb);
13267
13268 #if 0
13269     /* if debug information required */
13270     if (options.debug && currFunc) {
13271       if (currFunc) {
13272         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13273       }
13274     }
13275 #endif
13276
13277     for (ic = lic ; ic ; ic = ic->next ) {
13278
13279       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13280       if ( cln != ic->lineno ) {
13281         if ( options.debug ) {
13282           debugFile->writeCLine (ic);
13283         }
13284         
13285         if(!options.noCcodeInAsm) {
13286           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13287               printCLine(ic->filename, ic->lineno)));
13288         }
13289
13290         cln = ic->lineno ;
13291       }
13292         
13293       if(options.iCodeInAsm) {
13294         char *l;
13295
13296           /* insert here code to print iCode as comment */
13297           l = Safe_strdup(printILine(ic));
13298           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13299       }
13300         
13301       /* if the result is marked as
13302        * spilt and rematerializable or code for
13303        * this has already been generated then
13304        * do nothing */
13305       if (resultRemat(ic) || ic->generated ) 
13306         continue ;
13307         
13308       /* depending on the operation */
13309       switch (ic->op) {
13310         case '!' :
13311           pic16_genNot(ic);
13312           break;
13313             
13314         case '~' :
13315           pic16_genCpl(ic);
13316           break;
13317             
13318         case UNARYMINUS:
13319           genUminus (ic);
13320           break;
13321             
13322         case IPUSH:
13323           genIpush (ic);
13324           break;
13325             
13326         case IPOP:
13327           /* IPOP happens only when trying to restore a 
13328            * spilt live range, if there is an ifx statement
13329            * following this pop then the if statement might
13330            * be using some of the registers being popped which
13331            * would destroy the contents of the register so
13332            * we need to check for this condition and handle it */
13333            if (ic->next
13334              && ic->next->op == IFX
13335              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13336                genIfx (ic->next,ic);
13337           else
13338             genIpop (ic);
13339           break; 
13340             
13341         case CALL:
13342           genCall (ic);
13343           break;
13344             
13345         case PCALL:
13346           genPcall (ic);
13347           break;
13348             
13349         case FUNCTION:
13350           genFunction (ic);
13351           break;
13352             
13353         case ENDFUNCTION:
13354           genEndFunction (ic);
13355           break;
13356             
13357         case RETURN:
13358           genRet (ic);
13359           break;
13360             
13361         case LABEL:
13362           genLabel (ic);
13363           break;
13364             
13365         case GOTO:
13366           genGoto (ic);
13367           break;
13368             
13369         case '+' :
13370           pic16_genPlus (ic) ;
13371           break;
13372             
13373         case '-' :
13374           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13375             pic16_genMinus (ic);
13376           break;
13377
13378         case '*' :
13379           genMult (ic);
13380           break;
13381             
13382         case '/' :
13383           genDiv (ic) ;
13384           break;
13385             
13386         case '%' :
13387           genMod (ic);
13388           break;
13389             
13390         case '>' :
13391           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13392           break;
13393             
13394         case '<' :
13395           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13396           break;
13397             
13398         case LE_OP:
13399         case GE_OP:
13400         case NE_OP:
13401           /* note these two are xlated by algebraic equivalence
13402            * during parsing SDCC.y */
13403           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13404             "got '>=' or '<=' shouldn't have come here");
13405           break;
13406
13407         case EQ_OP:
13408           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13409           break;            
13410             
13411         case AND_OP:
13412           genAndOp (ic);
13413           break;
13414             
13415         case OR_OP:
13416           genOrOp (ic);
13417           break;
13418             
13419         case '^' :
13420           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13421           break;
13422             
13423         case '|' :
13424           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13425           break;
13426             
13427         case BITWISEAND:
13428           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13429           break;
13430             
13431         case INLINEASM:
13432           genInline (ic);
13433           break;
13434             
13435         case RRC:
13436           genRRC (ic);
13437           break;
13438             
13439         case RLC:
13440           genRLC (ic);
13441           break;
13442             
13443         case GETHBIT:
13444           genGetHbit (ic);
13445           break;
13446             
13447         case LEFT_OP:
13448           genLeftShift (ic);
13449           break;
13450             
13451         case RIGHT_OP:
13452           genRightShift (ic);
13453           break;
13454             
13455         case GET_VALUE_AT_ADDRESS:
13456           genPointerGet(ic);
13457           break;
13458             
13459         case '=' :
13460           if (POINTER_SET(ic))
13461             genPointerSet(ic);
13462           else
13463             genAssign(ic);
13464           break;
13465             
13466         case IFX:
13467           genIfx (ic,NULL);
13468           break;
13469             
13470         case ADDRESS_OF:
13471           genAddrOf (ic);
13472           break;
13473             
13474         case JUMPTABLE:
13475           genJumpTab (ic);
13476           break;
13477             
13478         case CAST:
13479           genCast (ic);
13480           break;
13481             
13482         case RECEIVE:
13483           genReceive(ic);
13484           break;
13485             
13486         case SEND:
13487           addSet(&_G.sendSet,ic);
13488           break;
13489
13490         case DUMMY_READ_VOLATILE:
13491           genDummyRead (ic);
13492           break;
13493
13494         default :
13495           ic = ic;
13496       }
13497     }
13498
13499
13500     /* now we are ready to call the
13501        peep hole optimizer */
13502     if (!options.nopeep)
13503       peepHole (&lineHead);
13504
13505     /* now do the actual printing */
13506     printLine (lineHead, codeOutFile);
13507
13508 #ifdef PCODE_DEBUG
13509     DFPRINTF((stderr,"printing pBlock\n\n"));
13510     pic16_printpBlock(stdout,pb);
13511 #endif
13512
13513     return;
13514 }
13515