]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
* .version: bumped version number to 2.4.8
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int interruptvector;
157     int usefastretfie;
158     bitVect *fregsUsed;
159     int stack_lat;                      /* stack offset latency */
160     int resDirect;
161     int useWreg;                        /* flag when WREG is used to pass function parameter */
162 } _G;
163
164 /* Resolved ifx structure. This structure stores information
165    about an iCode ifx that makes it easier to generate code.
166 */
167 typedef struct resolvedIfx {
168   symbol *lbl;     /* pointer to a label */
169   int condition;   /* true or false ifx */
170   int generated;   /* set true when the code associated with the ifx
171                     * is generated */
172 } resolvedIfx;
173
174 extern int pic16_ptrRegReq ;
175 extern int pic16_nRegs;
176 extern FILE *codeOutFile;
177 //static void saverbank (int, iCode *,bool);
178
179 static lineNode *lineHead = NULL;
180 static lineNode *lineCurr = NULL;
181
182 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
183 0xE0, 0xC0, 0x80, 0x00};
184 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
185 0x07, 0x03, 0x01, 0x00};
186
187 static  pBlock *pb;
188
189 /*-----------------------------------------------------------------*/
190 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
191 /*                 exponent of 2 is returned, otherwise -1 is      */
192 /*                 returned.                                       */
193 /* note that this is similar to the function `powof2' in SDCCsymt  */
194 /* if(n == 2^y)                                                    */
195 /*   return y;                                                     */
196 /* return -1;                                                      */
197 /*-----------------------------------------------------------------*/
198 int pic16_my_powof2 (unsigned long num)
199 {
200   if(num) {
201     if( (num & (num-1)) == 0) {
202       int nshifts = -1;
203       while(num) {
204         num>>=1;
205         nshifts++;
206       }
207       return nshifts;
208     }
209   }
210
211   return -1;
212 }
213
214 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
215 {
216   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
217                        line_no,
218                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
219                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
220                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
221                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
222                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
223                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
224                        ((result) ? AOP_SIZE(result) : 0));
225 }
226
227 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
228 {
229
230   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
231                        line_no,
232                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
233                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
234                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
235                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
236                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
237                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
238
239 }
240
241 void pic16_emitpcomment (char *fmt, ...)
242 {
243     va_list ap;
244     char lb[INITIAL_INLINEASM];  
245     char *lbp = lb;
246
247     va_start(ap,fmt);   
248
249     lb[0] = ';';
250     vsprintf(lb+1,fmt,ap);
251
252     while (isspace(*lbp)) lbp++;
253
254     if (lbp && *lbp) 
255         lineCurr = (lineCurr ?
256                     connectLine(lineCurr,newLineNode(lb)) :
257                     (lineHead = newLineNode(lb)));
258     lineCurr->isInline = _G.inLine;
259     lineCurr->isDebug  = _G.debugLine;
260
261     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
262     va_end(ap);
263
264 //      fprintf(stderr, "%s\n", lb);
265 }
266
267 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
268 {
269     va_list ap;
270     char lb[INITIAL_INLINEASM];  
271     char *lbp = lb;
272
273     if(!pic16_debug_verbose)
274       return;
275
276     va_start(ap,fmt);   
277
278     if (inst && *inst) {
279         if (fmt && *fmt)
280             sprintf(lb,"%s\t",inst);
281         else
282             sprintf(lb,"%s",inst);
283         vsprintf(lb+(strlen(lb)),fmt,ap);
284     }  else
285         vsprintf(lb,fmt,ap);
286
287     while (isspace(*lbp)) lbp++;
288
289     if (lbp && *lbp) 
290         lineCurr = (lineCurr ?
291                     connectLine(lineCurr,newLineNode(lb)) :
292                     (lineHead = newLineNode(lb)));
293     lineCurr->isInline = _G.inLine;
294     lineCurr->isDebug  = _G.debugLine;
295
296     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
297     va_end(ap);
298
299 //      fprintf(stderr, "%s\n", lb);
300 }
301
302
303
304 void pic16_emitpLabel(int key)
305 {
306   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
307 }
308
309 void pic16_emitpLabelFORCE(int key)
310 {
311   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
312 }
313
314 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
315 {
316
317   if(pcop)
318     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
319   else
320     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
321 }
322
323 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
324 {
325   if(pcop)
326     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
327   else
328     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
329 }
330   
331 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
332 {
333
334   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
335
336 }
337
338
339 #if 1
340 #define pic16_emitcode  DEBUGpic16_emitcode
341 #else
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitcode - writes the code into a file : for now it is simple    */
344 /*-----------------------------------------------------------------*/
345 void pic16_emitcode (char *inst,char *fmt, ...)
346 {
347     va_list ap;
348     char lb[INITIAL_INLINEASM];  
349     char *lbp = lb;
350
351     va_start(ap,fmt);   
352
353     if (inst && *inst) {
354         if (fmt && *fmt)
355             sprintf(lb,"%s\t",inst);
356         else
357             sprintf(lb,"%s",inst);
358         vsprintf(lb+(strlen(lb)),fmt,ap);
359     }  else
360         vsprintf(lb,fmt,ap);
361
362     while (isspace(*lbp)) lbp++;
363
364     if (lbp && *lbp) 
365         lineCurr = (lineCurr ?
366                     connectLine(lineCurr,newLineNode(lb)) :
367                     (lineHead = newLineNode(lb)));
368     lineCurr->isInline = _G.inLine;
369     lineCurr->isDebug  = _G.debugLine;
370
371 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
372
373 //    if(pic16_debug_verbose)
374 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
375
376     va_end(ap);
377 }
378 #endif
379
380
381 /*-----------------------------------------------------------------*/
382 /* pic16_emitDebuggerSymbol - associate the current code location  */
383 /*   with a debugger symbol                                        */
384 /*-----------------------------------------------------------------*/
385 void
386 pic16_emitDebuggerSymbol (char * debugSym)
387 {
388   _G.debugLine = 1;
389   pic16_emitcode (";", "%s ==.", debugSym);
390   _G.debugLine = 0;
391 }
392
393
394 /*-----------------------------------------------------------------*/
395 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
396 /*-----------------------------------------------------------------*/
397 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
398 {
399 //    bool r0iu = FALSE , r1iu = FALSE;
400 //    bool r0ou = FALSE , r1ou = FALSE;
401     bool fsr0iu = FALSE, fsr0ou;
402     bool fsr2iu = FALSE, fsr2ou;
403     
404     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
405
406     
407     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
408     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
409     
410     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
411     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
412
413     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
414         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
415         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
416     }
417
418     if(!fsr0iu && !fsr0ou) {
419         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
420         (*aopp)->type = AOP_FSR0;
421
422         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
423         
424       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
425     }
426
427 #if 0
428     /* no usage of FSR2 */
429     if(!fsr2iu && !fsr2ou) {
430         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
431         (*aopp)->type = AOP_FSR2;
432
433       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
434     }
435 #endif
436         
437     /* now we know they both have usage */
438     /* if fsr0 not used in this instruction */
439     if (!fsr0iu) {
440         if (!_G.fsr0Pushed) {
441                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
442                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
443                 _G.fsr0Pushed++;
444         }
445
446         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
447         (*aopp)->type = AOP_FSR0;
448
449 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
450
451       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
452     }
453         
454
455     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
456     assert( 0 );
457
458     return NULL;
459 #if 0
460     /* the logic: if r0 & r1 used in the instruction
461     then we are in trouble otherwise */
462
463     /* first check if r0 & r1 are used by this
464     instruction, in which case we are in trouble */
465     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
466         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
467     {
468         goto endOfWorld;      
469     }
470
471     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
472     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
473
474     /* if no usage of r0 then return it */
475     if (!r0iu && !r0ou) {
476         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
477         (*aopp)->type = AOP_R0; 
478         
479         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
480     }
481
482     /* if no usage of r1 then return it */
483     if (!r1iu && !r1ou) {
484         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
485         (*aopp)->type = AOP_R1;
486
487         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
488     }    
489
490     /* now we know they both have usage */
491     /* if r0 not used in this instruction */
492     if (!r0iu) {
493         /* push it if not already pushed */
494         if (!_G.r0Pushed) {
495           //pic16_emitcode ("push","%s",
496           //          pic16_regWithIdx(R0_IDX)->dname);
497             _G.r0Pushed++ ;
498         }
499         
500         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
501         (*aopp)->type = AOP_R0;
502
503         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
504     }
505
506     /* if r1 not used then */
507
508     if (!r1iu) {
509         /* push it if not already pushed */
510         if (!_G.r1Pushed) {
511           //pic16_emitcode ("push","%s",
512           //          pic16_regWithIdx(R1_IDX)->dname);
513             _G.r1Pushed++ ;
514         }
515         
516         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
517         (*aopp)->type = AOP_R1;
518         return pic16_regWithIdx(R1_IDX);
519     }
520
521 endOfWorld :
522     /* I said end of world but not quite end of world yet */
523     /* if this is a result then we can push it on the stack*/
524     if (result) {
525         (*aopp)->type = AOP_STK;    
526         return NULL;
527     }
528
529     /* other wise this is true end of the world */
530     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
531            "getFreePtr should never reach here");
532     exit(0);
533 #endif
534 }
535
536 /*-----------------------------------------------------------------*/
537 /* newAsmop - creates a new asmOp                                  */
538 /*-----------------------------------------------------------------*/
539 static asmop *newAsmop (short type)
540 {
541     asmop *aop;
542
543     aop = Safe_calloc(1,sizeof(asmop));
544     aop->type = type;
545     return aop;
546 }
547
548 static void genSetDPTR(int n)
549 {
550     if (!n)
551     {
552         pic16_emitcode(";", "Select standard DPTR");
553         pic16_emitcode("mov", "dps, #0x00");
554     }
555     else
556     {
557         pic16_emitcode(";", "Select alternate DPTR");
558         pic16_emitcode("mov", "dps, #0x01");
559     }
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* resolveIfx - converts an iCode ifx into a form more useful for  */
564 /*              generating code                                    */
565 /*-----------------------------------------------------------------*/
566 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
567 {
568   FENTRY2;
569   
570 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
571
572   if(!resIfx) 
573     return;
574
575
576   resIfx->condition = 1;    /* assume that the ifx is true */
577   resIfx->generated = 0;    /* indicate that the ifx has not been used */
578
579   if(!ifx) {
580     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
581
582 #if 1
583     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
584                         __FUNCTION__,__LINE__,resIfx->lbl->key);
585 #endif
586
587   } else {
588     if(IC_TRUE(ifx)) {
589       resIfx->lbl = IC_TRUE(ifx);
590     } else {
591       resIfx->lbl = IC_FALSE(ifx);
592       resIfx->condition = 0;
593     }
594
595 #if 1
596     if(IC_TRUE(ifx)) 
597       DEBUGpic16_emitcode("; +++","ifx true is non-null");
598     else
599       DEBUGpic16_emitcode("; +++","ifx true is null");
600     if(IC_FALSE(ifx)) 
601       DEBUGpic16_emitcode("; +++","ifx false is non-null");
602     else
603       DEBUGpic16_emitcode("; +++","ifx false is null");
604 #endif
605   }
606
607   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
608
609 }
610 #if 0
611 /*-----------------------------------------------------------------*/
612 /* pointerCode - returns the code for a pointer type               */
613 /*-----------------------------------------------------------------*/
614 static int pointerCode (sym_link *etype)
615 {
616
617     return PTR_TYPE(SPEC_OCLS(etype));
618
619 }
620 #endif
621
622 /*-----------------------------------------------------------------*/
623 /* aopForSym - for a true symbol                                   */
624 /*-----------------------------------------------------------------*/
625 static asmop *aopForSym (iCode *ic, operand *op, bool result)
626 {
627     symbol *sym=OP_SYMBOL(op);
628     asmop *aop;
629     memmap *space= SPEC_OCLS(sym->etype);
630
631     FENTRY2;
632     
633     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
634     
635 //    sym = OP_SYMBOL(op);
636
637     /* if already has one */
638     if (sym->aop) {
639             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
640         return sym->aop;
641     }
642
643 #if 0
644     /* if symbol was initially placed onStack then we must re-place it
645      * to direct memory, since pic16 does not have a specific stack */
646     if(sym->onStack) {
647         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
648     }
649 #endif
650
651
652 #if 0
653     if(sym->iaccess) {
654       if(space->paged) {
655         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
656
657         sym->aop = aop = newAsmop (AOP_PAGED);
658         aop->aopu.aop_dir = sym->rname ;
659         aop->size = getSize(sym->type);
660         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
661         pic16_allocDirReg( IC_LEFT(ic) );
662         return aop;
663       }
664       assert( 0 );
665     }
666 #endif
667     
668 #if 1
669     /* assign depending on the storage class */
670     /* if it is on the stack or indirectly addressable */
671     /* space we need to assign either r0 or r1 to it   */    
672     if (sym->onStack)   // || sym->iaccess)
673     {
674       pCodeOp *pcop[4];
675       int i;
676       
677         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
678                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
679         
680         /* acquire a temporary register -- it is saved in function */
681
682         sym->aop = aop = newAsmop(AOP_STA);
683         aop->aopu.stk.stk = sym->stack;
684         aop->size = getSize(sym->type);
685
686
687         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
688         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
689           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
690           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
691           
692           for(i=0;i<aop->size;i++)
693             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
694             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
695         } else
696           for(i=0;i<aop->size;i++) {
697             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
698             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
699           }
700
701
702 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
703
704 #if 1
705         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
706         
707         if(_G.accInUse) {
708                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
709         }
710         
711         for(i=0;i<aop->size;i++) {
712
713           /* initialise for stack access via frame pointer */
714           // operands on stack are accessible via "FSR2 + index" with index
715           // starting at 2 for arguments and growing from 0 downwards for
716           // local variables (index == 0 is not assigned so we add one here)
717           {
718             int soffs = sym->stack;
719             if (soffs <= 0) {
720               assert (soffs < 0);
721               soffs++;
722             } // if
723             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
724             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
725                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
726           }
727         }
728         
729         if(_G.accInUse) {
730                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
731         }
732         
733         return (aop);
734 #endif
735
736 #if 0
737         /* now assign the address of the variable to 
738         the pointer register */
739         if (aop->type != AOP_STK) {
740
741             if (sym->onStack) {
742                     if ( _G.accInUse )
743                         pic16_emitcode("push","acc");
744
745                     pic16_emitcode("mov","a,_bp");
746                     pic16_emitcode("add","a,#0x%02x",
747                              ((sym->stack < 0) ?
748                               ((char)(sym->stack - _G.nRegsSaved )) :
749                               ((char)sym->stack)) & 0xff);
750                     pic16_emitcode("mov","%s,a",
751                              aop->aopu.aop_ptr->name);
752
753                     if ( _G.accInUse )
754                         pic16_emitcode("pop","acc");
755             } else
756                 pic16_emitcode("mov","%s,#%s",
757                          aop->aopu.aop_ptr->name,
758                          sym->rname);
759             aop->paged = space->paged;
760         } else
761             aop->aopu.aop_stk = sym->stack;
762         return aop;
763 #endif
764
765     }
766 #endif
767
768 #if 0
769     if (sym->onStack && options.stack10bit)
770     {
771         /* It's on the 10 bit stack, which is located in
772          * far data space.
773          */
774          
775       //DEBUGpic16_emitcode(";","%d",__LINE__);
776
777         if ( _G.accInUse )
778                 pic16_emitcode("push","acc");
779
780         pic16_emitcode("mov","a,_bp");
781         pic16_emitcode("add","a,#0x%02x",
782                  ((sym->stack < 0) ?
783                    ((char)(sym->stack - _G.nRegsSaved )) :
784                    ((char)sym->stack)) & 0xff);
785         
786         genSetDPTR(1);
787         pic16_emitcode ("mov","dpx1,#0x40");
788         pic16_emitcode ("mov","dph1,#0x00");
789         pic16_emitcode ("mov","dpl1, a");
790         genSetDPTR(0);
791         
792         if ( _G.accInUse )
793             pic16_emitcode("pop","acc");
794             
795         sym->aop = aop = newAsmop(AOP_DPTR2);
796         aop->size = getSize(sym->type); 
797         return aop;
798     }
799 #endif
800
801 #if 0
802     /* special case for a function */
803     if (IS_FUNC(sym->type)) {   
804         sym->aop = aop = newAsmop(AOP_PCODE);
805         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
806         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
807         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
808         PCOI(aop->aopu.pcop)->index = 0;
809         aop->size = FPTRSIZE; 
810         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
811         return aop;
812     }
813 #endif
814
815
816
817     //DEBUGpic16_emitcode(";","%d",__LINE__);
818     /* if in bit space */
819     if (IN_BITSPACE(space)) {
820         sym->aop = aop = newAsmop (AOP_CRY);
821         aop->aopu.aop_dir = sym->rname ;
822         aop->size = getSize(sym->type);
823         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
824         return aop;
825     }
826     /* if it is in direct space */
827     if (IN_DIRSPACE(space)) {
828         sym->aop = aop = newAsmop (AOP_DIR);
829         aop->aopu.aop_dir = sym->rname ;
830         aop->size = getSize(sym->type);
831         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
832         pic16_allocDirReg( IC_LEFT(ic) );
833         return aop;
834     }
835
836
837     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
838         sym->aop = aop = newAsmop (AOP_DIR);
839         aop->aopu.aop_dir = sym->rname ;
840         aop->size = getSize(sym->type);
841         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
842         pic16_allocDirReg( IC_LEFT(ic) );
843         return aop;
844     }
845
846
847     /* only remaining is far space */
848     sym->aop = aop = newAsmop(AOP_PCODE);
849
850 /* change the next if to 1 to revert to good old immediate code */
851         if(IN_CODESPACE(space)) {
852                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
853                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
854                 PCOI(aop->aopu.pcop)->index = 0;
855         } else {
856                 /* try to allocate via direct register */
857                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
858 //              aop->size = getSize( sym->type );
859         }
860
861         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
862                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
863
864 #if 0
865         if(!pic16_allocDirReg (IC_LEFT(ic)))
866                 return NULL;
867 #endif
868
869         if(IN_DIRSPACE( space ))
870                 aop->size = PTRSIZE;
871         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
872                 aop->size = FPTRSIZE;
873         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
874         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
875         else if(sym->onStack) {
876                 aop->size = PTRSIZE;
877         } else {
878           if(SPEC_SCLS(sym->etype) == S_PDATA) {
879             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
880             aop->size = FPTRSIZE;
881           } else
882                 assert( 0 );
883         }
884
885     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
886
887     /* if it is in code space */
888     if (IN_CODESPACE(space))
889         aop->code = 1;
890
891     return aop;     
892 }
893
894 /*-----------------------------------------------------------------*/
895 /* aopForRemat - rematerialzes an object                           */
896 /*-----------------------------------------------------------------*/
897 static asmop *aopForRemat (operand *op) // x symbol *sym)
898 {
899   symbol *sym = OP_SYMBOL(op);
900   operand *refop;
901   iCode *ic = NULL, *oldic;
902   asmop *aop = newAsmop(AOP_PCODE);
903   int val = 0;
904   int offset = 0;
905   int viaimmd=0;
906
907     FENTRY2;
908     
909         ic = sym->rematiCode;
910
911         if(IS_OP_POINTER(op)) {
912                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
913         }
914
915         for (;;) {
916                 oldic = ic;
917
918 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
919         
920                 if (ic->op == '+') {
921                         val += (int) operandLitValue(IC_RIGHT(ic));
922                 } else if (ic->op == '-') {
923                         val -= (int) operandLitValue(IC_RIGHT(ic));
924                 } else
925                         break;
926                 
927                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
928         }
929
930         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
931         refop = IC_LEFT(ic);
932
933         if(!op->isaddr)viaimmd++; else viaimmd=0;
934                 
935 /* set the following if to 1 to revert to good old immediate code */
936         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
937                 || viaimmd) {
938
939                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
940
941                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
942
943 #if 0
944                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
945 #else
946                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
947 #endif
948
949                 PCOI(aop->aopu.pcop)->index = val;
950                 
951                 aop->size = getSize( sym->type );
952         } else {
953                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
954
955                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
956                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
957
958                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
959         }
960
961
962         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
963                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
964 #if 0
965                 val, IS_PTR_CONST(operandType(op)));
966 #else
967                 val, IS_CODEPTR(operandType(op)));
968 #endif
969
970 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
971
972         pic16_allocDirReg (IC_LEFT(ic));
973
974         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
975                 aop->code = 1;
976
977   return aop;        
978 }
979
980 #if 0
981 static int aopIdx (asmop *aop, int offset)
982 {
983   if(!aop)
984     return -1;
985
986   if(aop->type !=  AOP_REG)
987     return -2;
988         
989   return aop->aopu.aop_reg[offset]->rIdx;
990
991 }
992 #endif
993
994 /*-----------------------------------------------------------------*/
995 /* regsInCommon - two operands have some registers in common       */
996 /*-----------------------------------------------------------------*/
997 static bool regsInCommon (operand *op1, operand *op2)
998 {
999     symbol *sym1, *sym2;
1000     int i;
1001
1002     /* if they have registers in common */
1003     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1004         return FALSE ;
1005
1006     sym1 = OP_SYMBOL(op1);
1007     sym2 = OP_SYMBOL(op2);
1008
1009     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1010         return FALSE ;
1011
1012     for (i = 0 ; i < sym1->nRegs ; i++) {
1013         int j;
1014         if (!sym1->regs[i])
1015             continue ;
1016
1017         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1018             if (!sym2->regs[j])
1019                 continue ;
1020
1021             if (sym2->regs[j] == sym1->regs[i])
1022                 return TRUE ;
1023         }
1024     }
1025
1026     return FALSE ;
1027 }
1028
1029 /*-----------------------------------------------------------------*/
1030 /* operandsEqu - equivalent                                        */
1031 /*-----------------------------------------------------------------*/
1032 static bool operandsEqu ( operand *op1, operand *op2)
1033 {
1034     symbol *sym1, *sym2;
1035
1036     /* if they not symbols */
1037     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1038         return FALSE;
1039
1040     sym1 = OP_SYMBOL(op1);
1041     sym2 = OP_SYMBOL(op2);
1042
1043     /* if both are itemps & one is spilt
1044        and the other is not then false */
1045     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1046         sym1->isspilt != sym2->isspilt )
1047         return FALSE ;
1048
1049     /* if they are the same */
1050     if (sym1 == sym2)
1051         return TRUE ;
1052
1053     if (sym1->rname[0] && sym2->rname[0]
1054         && strcmp (sym1->rname, sym2->rname) == 0)
1055         return TRUE;
1056
1057
1058     /* if left is a tmp & right is not */
1059     if (IS_ITEMP(op1)  && 
1060         !IS_ITEMP(op2) &&
1061         sym1->isspilt  &&
1062         (sym1->usl.spillLoc == sym2))
1063         return TRUE;
1064
1065     if (IS_ITEMP(op2)  && 
1066         !IS_ITEMP(op1) &&
1067         sym2->isspilt  &&
1068         sym1->level > 0 &&
1069         (sym2->usl.spillLoc == sym1))
1070         return TRUE ;
1071
1072     return FALSE ;
1073 }
1074
1075 /*-----------------------------------------------------------------*/
1076 /* pic16_sameRegs - two asmops have the same registers                   */
1077 /*-----------------------------------------------------------------*/
1078 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1079 {
1080     int i;
1081
1082     if (aop1 == aop2)
1083         return TRUE ;
1084
1085     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1086                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1087
1088     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1089
1090     if (aop1->type != AOP_REG ||
1091         aop2->type != AOP_REG )
1092         return FALSE ;
1093
1094     /* This is a bit too restrictive if one is a subset of the other...
1095     if (aop1->size != aop2->size )
1096         return FALSE ;
1097     */
1098
1099     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1100 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1101
1102 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1103         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1104             return FALSE ;
1105     }
1106
1107     return TRUE ;
1108 }
1109
1110 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1111 {
1112     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1113                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1114
1115     if(aop1 == aop2)return TRUE;
1116     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1117       
1118       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1119     
1120   return TRUE;
1121 }
1122
1123
1124 /*-----------------------------------------------------------------*/
1125 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1126 /*-----------------------------------------------------------------*/
1127 void pic16_aopOp (operand *op, iCode *ic, bool result)
1128 {
1129     asmop *aop;
1130     symbol *sym;
1131     int i;
1132
1133     if (!op)
1134         return ;
1135
1136     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1137
1138     /* if this a literal */
1139     if (IS_OP_LITERAL(op)) {
1140         op->aop = aop = newAsmop(AOP_LIT);
1141         aop->aopu.aop_lit = op->operand.valOperand;
1142         aop->size = getSize(operandType(op));
1143         return;
1144     }
1145
1146     {
1147       sym_link *type = operandType(op);
1148 #if 0
1149       if(IS_PTR_CONST(type))
1150 #else
1151       if(IS_CODEPTR(type))
1152 #endif
1153         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1154     }
1155
1156     /* if already has a asmop then continue */
1157     if (op->aop)
1158         return ;
1159
1160     /* if the underlying symbol has a aop */
1161     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1162       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1163         op->aop = OP_SYMBOL(op)->aop;
1164         return;
1165     }
1166
1167     /* if this is a true symbol */
1168     if (IS_TRUE_SYMOP(op)) {    
1169         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1170       op->aop = aopForSym(ic, op, result);
1171       return ;
1172     }
1173
1174     /* this is a temporary : this has
1175     only four choices :
1176     a) register
1177     b) spillocation
1178     c) rematerialize 
1179     d) conditional   
1180     e) can be a return use only */
1181
1182     sym = OP_SYMBOL(op);
1183
1184     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1185     /* if the type is a conditional */
1186     if (sym->regType == REG_CND) {
1187         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1188         aop->size = 0;
1189         return;
1190     }
1191
1192     /* if it is spilt then two situations
1193     a) is rematerialize 
1194     b) has a spill location */
1195     if (sym->isspilt || sym->nRegs == 0) {
1196
1197 //      debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
1198       DEBUGpic16_emitcode(";","%d",__LINE__);
1199         /* rematerialize it NOW */
1200         if (sym->remat) {
1201
1202             sym->aop = op->aop = aop = aopForRemat (op);
1203 //            aop->size = getSize(sym->type);
1204 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1205             return;
1206         }
1207
1208 #if 1
1209         if (sym->accuse) {
1210             int i;
1211             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1212             aop->size = getSize(sym->type);
1213             for ( i = 0 ; i < 1 ; i++ ) {
1214                 aop->aopu.aop_str[i] = accUse[i];
1215 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1216             }
1217             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1218             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1219             return;  
1220         }
1221 #endif
1222
1223 #if 1
1224         if (sym->ruonly ) {
1225           /*
1226           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1227           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1228           //pic16_allocDirReg (IC_LEFT(ic));
1229           aop->size = getSize(sym->type);
1230           */
1231
1232           unsigned i;
1233
1234           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1235           aop->size = getSize(sym->type);
1236           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1237             aop->aopu.aop_str[i] = fReturn[i];
1238
1239           DEBUGpic16_emitcode(";","%d",__LINE__);
1240           return;
1241         }
1242 #endif
1243         /* else spill location  */
1244         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1245             /* force a new aop if sizes differ */
1246             sym->usl.spillLoc->aop = NULL;
1247         }
1248
1249 #if 0
1250         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1251                             __FUNCTION__,__LINE__,
1252                             sym->usl.spillLoc->rname,
1253                             sym->rname, sym->usl.spillLoc->offset);
1254 #endif
1255
1256         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1257         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1258         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1259                                           getSize(sym->type), 
1260                                           sym->usl.spillLoc->offset, op);
1261         aop->size = getSize(sym->type);
1262
1263         return;
1264     }
1265
1266     {
1267       sym_link *type = operandType(op);
1268 #if 0
1269       if(IS_PTR_CONST(type)) 
1270 #else
1271       if(IS_CODEPTR(type)) 
1272 #endif
1273         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1274     }
1275
1276     /* must be in a register */
1277     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1278     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1279     aop->size = sym->nRegs;
1280     for ( i = 0 ; i < sym->nRegs ;i++)
1281         aop->aopu.aop_reg[i] = sym->regs[i];
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_freeAsmop - free up the asmop given to an operand               */
1286 /*----------------------------------------------------------------*/
1287 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1288 {   
1289     asmop *aop ;
1290
1291     if (!op)
1292         aop = aaop;
1293     else 
1294         aop = op->aop;
1295
1296     if (!aop)
1297         return ;
1298
1299     if (aop->freed)
1300         goto dealloc; 
1301
1302     aop->freed = 1;
1303
1304     /* depending on the asmop type only three cases need work AOP_RO
1305        , AOP_R1 && AOP_STK */
1306 #if 1
1307     switch (aop->type) {
1308         case AOP_FSR0 :
1309             if (_G.fsr0Pushed ) {
1310                 if (pop) {
1311                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1312                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1313 //                    pic16_emitcode ("pop","ar0");
1314                     _G.fsr0Pushed--;
1315                 }
1316             }
1317             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1318             break;
1319
1320         case AOP_FSR2 :
1321             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1322             break;
1323
1324         case AOP_R0 :
1325             if (_G.r0Pushed ) {
1326                 if (pop) {
1327                     pic16_emitcode ("pop","ar0");     
1328                     _G.r0Pushed--;
1329                 }
1330             }
1331             bitVectUnSetBit(ic->rUsed,R0_IDX);
1332             break;
1333
1334         case AOP_R1 :
1335             if (_G.r1Pushed ) {
1336                 if (pop) {
1337                     pic16_emitcode ("pop","ar1");
1338                     _G.r1Pushed--;
1339                 }
1340             }
1341             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1342             break;
1343
1344         case AOP_STA:
1345           {
1346             int i;
1347
1348               /* we must store the result on stack */
1349               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1350                 // operands on stack are accessible via "FSR2 + index" with index
1351                 // starting at 2 for arguments and growing from 0 downwards for
1352                 // local variables (index == 0 is not assigned so we add one here)
1353                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1354                 if (soffs <= 0) {
1355                   assert (soffs < 0);
1356                   soffs++;
1357                 } // if
1358                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1359                 for(i=0;i<aop->size;i++) {
1360                   /* initialise for stack access via frame pointer */
1361                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1362                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1363                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1364                 }
1365         
1366                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1367               }
1368
1369               if(!_G.resDirect) {
1370                 for(i=0;i<aop->size;i++)
1371                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1372               }
1373               _G.resDirect = 0;
1374           }
1375           break;
1376 #if 0
1377         case AOP_STK :
1378         {
1379             int sz = aop->size;    
1380             int stk = aop->aopu.aop_stk + aop->size;
1381             bitVectUnSetBit(ic->rUsed,R0_IDX);
1382             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1383
1384             getFreePtr(ic,&aop,FALSE);
1385             
1386             if (options.stack10bit)
1387             {
1388                 /* I'm not sure what to do here yet... */
1389                 /* #STUB */
1390                 fprintf(stderr, 
1391                         "*** Warning: probably generating bad code for "
1392                         "10 bit stack mode.\n");
1393             }
1394             
1395             if (stk) {
1396                 pic16_emitcode ("mov","a,_bp");
1397                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1398                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1399             } else {
1400                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1401             }
1402
1403             while (sz--) {
1404                 pic16_emitcode("pop","acc");
1405                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1406                 if (!sz) break;
1407                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1408             }
1409             op->aop = aop;
1410             pic16_freeAsmop(op,NULL,ic,TRUE);
1411             if (_G.r0Pushed) {
1412                 pic16_emitcode("pop","ar0");
1413                 _G.r0Pushed--;
1414             }
1415
1416             if (_G.r1Pushed) {
1417                 pic16_emitcode("pop","ar1");
1418                 _G.r1Pushed--;
1419             }       
1420         }
1421 #endif
1422
1423     }
1424 #endif
1425
1426 dealloc:
1427     /* all other cases just dealloc */
1428     if (op ) {
1429         op->aop = NULL;
1430         if (IS_SYMOP(op)) {
1431             OP_SYMBOL(op)->aop = NULL;    
1432             /* if the symbol has a spill */
1433             if (SPIL_LOC(op))
1434                 SPIL_LOC(op)->aop = NULL;
1435         }
1436     }
1437 }
1438
1439 /*-----------------------------------------------------------------*/
1440 /* pic16_aopGet - for fetching value of the aop                          */
1441 /*-----------------------------------------------------------------*/
1442 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1443 {
1444     char *s = buffer ;
1445     char *rs;
1446
1447     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1448
1449     /* offset is greater than size then zero */
1450     if (offset > (aop->size - 1) &&
1451         aop->type != AOP_LIT)
1452         return zero;
1453
1454     /* depending on type */
1455     switch (aop->type) {
1456
1457     case AOP_FSR0:
1458     case AOP_FSR2:
1459       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1460       rs = Safe_calloc(1, strlen(s)+1);
1461       strcpy(rs, s);
1462       return (rs);
1463       
1464 #if 0
1465       /* if we need to increment it */
1466       while (offset > aop->coff)
1467         {
1468           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1469           aop->coff++;
1470         }
1471
1472       while (offset < aop->coff)
1473         {
1474           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1475           aop->coff--;
1476         }
1477       aop->coff = offset;
1478       if (aop->paged)
1479         {
1480           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1481           return (dname ? "acc" : "a");
1482         }
1483       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1484       rs = Safe_calloc (1, strlen (s) + 1);
1485       strcpy (rs, s);
1486       return rs;
1487 #endif
1488
1489         
1490     case AOP_IMMD:
1491         if (bit16) 
1492             sprintf (s,"%s",aop->aopu.aop_immd);
1493         else
1494             if (offset) 
1495                 sprintf(s,"(%s >> %d)",
1496                         aop->aopu.aop_immd,
1497                         offset*8);
1498             else
1499                 sprintf(s,"%s",
1500                         aop->aopu.aop_immd);
1501         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1502         rs = Safe_calloc(1,strlen(s)+1);
1503         strcpy(rs,s);   
1504         return rs;
1505         
1506     case AOP_DIR:
1507       if (offset) {
1508         sprintf(s,"(%s + %d)",
1509                 aop->aopu.aop_dir,
1510                 offset);
1511         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1512       } else
1513             sprintf(s,"%s",aop->aopu.aop_dir);
1514         rs = Safe_calloc(1,strlen(s)+1);
1515         strcpy(rs,s);   
1516         return rs;
1517         
1518     case AOP_REG:
1519       //if (dname) 
1520       //    return aop->aopu.aop_reg[offset]->dname;
1521       //else
1522             return aop->aopu.aop_reg[offset]->name;
1523         
1524     case AOP_CRY:
1525       //pic16_emitcode(";","%d",__LINE__);
1526       return aop->aopu.aop_dir;
1527         
1528     case AOP_ACC:
1529         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1530 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1531 //        assert( 0 );
1532 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1533         rs = Safe_strdup("WREG");
1534         return (rs);
1535
1536     case AOP_LIT:
1537         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1538         rs = Safe_calloc(1,strlen(s)+1);
1539         strcpy(rs,s);   
1540         return rs;
1541         
1542     case AOP_STR:
1543         aop->coff = offset ;
1544         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1545             dname)
1546             return "acc";
1547         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1548         
1549         return aop->aopu.aop_str[offset];
1550         
1551     case AOP_PCODE:
1552       {
1553         pCodeOp *pcop = aop->aopu.pcop;
1554         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1555         if(pcop->name) {
1556           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1557           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1558           if (offset) {
1559             sprintf(s,"(%s + %d)", pcop->name, offset);
1560           } else {
1561             sprintf(s,"%s", pcop->name);
1562           }
1563         } else
1564           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1565
1566       }
1567       rs = Safe_calloc(1,strlen(s)+1);
1568       strcpy(rs,s);   
1569       return rs;
1570
1571 #if 0
1572     case AOP_PAGED:
1573       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1574       if (offset) {
1575         sprintf(s,"(%s + %d)",
1576                 aop->aopu.aop_dir,
1577                 offset);
1578       } else
1579             sprintf(s,"%s",aop->aopu.aop_dir);
1580       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1581       rs = Safe_calloc(1,strlen(s)+1);
1582       strcpy(rs,s);   
1583       return rs;
1584 #endif
1585
1586     case AOP_STA:
1587         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1588         return (rs);
1589         
1590     case AOP_STK:
1591 //        pCodeOp *pcop = aop->aop
1592         break;
1593
1594     }
1595
1596     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1597     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1598            "aopget got unsupported aop->type");
1599     exit(0);
1600 }
1601
1602
1603
1604 /* lock has the following meaning: When allocating temporary registers
1605  * for stack variables storage, the value of the temporary register is
1606  * saved on stack. Its value is restored at the end. This procedure is
1607  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1608  * a possibility that before a call to pic16_aopOp, a temporary register
1609  * is allocated for a while and it is freed after some time, this will
1610  * mess the stack and values will not be restored properly. So use lock=1
1611  * to allocate temporary registers used internally by the programmer, and
1612  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1613  * to inform the compiler developer about a possible bug. This is an internal
1614  * feature for developing the compiler -- VR */
1615  
1616 int _TempReg_lock = 0;
1617 /*-----------------------------------------------------------------*/
1618 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1619 /*-----------------------------------------------------------------*/
1620 pCodeOp *pic16_popGetTempReg(int lock)
1621 {
1622   pCodeOp *pcop;
1623   symbol *cfunc;
1624
1625 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1626     if(_TempReg_lock) {
1627 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1628     }
1629     
1630     _TempReg_lock += lock;
1631     
1632     cfunc = currFunc;
1633     currFunc = NULL;
1634
1635     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1636     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1637       PCOR(pcop)->r->wasUsed=1;
1638       PCOR(pcop)->r->isFree=0;
1639
1640       /* push value on stack */
1641       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1642     }
1643
1644     currFunc = cfunc;
1645
1646   return pcop;
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1651 /*                            don't save if inside v               */
1652 /*-----------------------------------------------------------------*/
1653 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1654 {
1655   pCodeOp *pcop;
1656   symbol *cfunc;
1657
1658 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1659
1660     if(_TempReg_lock) {
1661 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1662     }
1663
1664     _TempReg_lock += lock;
1665
1666     cfunc = currFunc;
1667     currFunc = NULL;
1668
1669     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1670     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1671       PCOR(pcop)->r->wasUsed=1;
1672       PCOR(pcop)->r->isFree=0;
1673
1674       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1675       /* push value on stack */
1676         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1677       }
1678     }
1679
1680     currFunc = cfunc;
1681
1682   return pcop;
1683 }
1684
1685
1686 /*-----------------------------------------------------------------*/
1687 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1688 /*-----------------------------------------------------------------*/
1689 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1690 {
1691   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1692
1693   _TempReg_lock -= lock;
1694
1695   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1696     PCOR(pcop)->r->isFree = 1;
1697     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1698   }
1699 }
1700 /*-----------------------------------------------------------------*/
1701 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1702 /*-----------------------------------------------------------------*/
1703 pCodeOp *pic16_popGetLabel(unsigned int key)
1704 {
1705
1706   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1707
1708   if(key>max_key)
1709     max_key = key;
1710
1711   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1712 }
1713
1714 /*-----------------------------------------------------------------*/
1715 /* pic16_popCopyReg - copy a pcode operator                              */
1716 /*-----------------------------------------------------------------*/
1717 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1718 {
1719   pCodeOpReg *pcor;
1720
1721   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1722   pcor->pcop.type = pc->pcop.type;
1723   if(pc->pcop.name) {
1724     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1725       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1726   } else
1727     pcor->pcop.name = NULL;
1728
1729   pcor->r = pc->r;
1730   pcor->rIdx = pc->rIdx;
1731   pcor->r->wasUsed=1;
1732   pcor->instance = pc->instance;
1733
1734 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1735
1736   return PCOP(pcor);
1737 }
1738
1739 /*-----------------------------------------------------------------*/
1740 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *pic16_popGetLit(int lit)
1743 {
1744   return pic16_newpCodeOpLit(lit);
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1749 /*-----------------------------------------------------------------*/
1750 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1751 {
1752   return pic16_newpCodeOpLit2(lit, arg2);
1753 }
1754
1755
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1758 /*-----------------------------------------------------------------*/
1759 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1760 {
1761   return pic16_newpCodeOpImmd(name, offset,index, 0);
1762 }
1763
1764
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_popGet - asm operator to pcode operator conversion              */
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *pic16_popGetWithString(char *str)
1769 {
1770   pCodeOp *pcop;
1771
1772
1773   if(!str) {
1774     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1775     exit (1);
1776   }
1777
1778   pcop = pic16_newpCodeOp(str,PO_STR);
1779
1780   return pcop;
1781 }
1782
1783 /*-----------------------------------------------------------------*/
1784 /* pic16_popRegFromString -                                        */
1785 /*-----------------------------------------------------------------*/
1786 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1787 {
1788
1789   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790   pcop->type = PO_DIR;
1791
1792   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1793   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1794
1795   if(!str)
1796     str = "BAD_STRING";
1797
1798   pcop->name = Safe_calloc(1,strlen(str)+1);
1799   strcpy(pcop->name,str);
1800
1801   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1802
1803   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1804
1805   /* make sure that register doesn't exist,
1806    * and operand isn't NULL
1807    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1808   if((PCOR(pcop)->r == NULL) 
1809     && (op)
1810     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1811 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1812 //              __FUNCTION__, __LINE__, str, size, offset);
1813
1814     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1815     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1816
1817   }
1818   PCOR(pcop)->instance = offset;
1819
1820   return pcop;
1821 }
1822
1823 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1824 {
1825   pCodeOp *pcop;
1826
1827 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1828
1829         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1830         PCOR(pcop)->rIdx = rIdx;
1831         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1832
1833         PCOR(pcop)->r->isFree = 0;
1834         PCOR(pcop)->r->wasUsed = 1;
1835
1836         pcop->type = PCOR(pcop)->r->pc_type;
1837
1838   return pcop;
1839 }
1840
1841 /*---------------------------------------------------------------------------------*/
1842 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1843 /*                 VR 030601                                                       */
1844 /*---------------------------------------------------------------------------------*/
1845 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1846 {
1847   pCodeOpReg2 *pcop2;
1848   pCodeOp *temp;
1849   
1850         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1851
1852         /* comment the following check, so errors to throw up */
1853 //      if(!pcop2)return NULL;
1854
1855         temp = pic16_popGet(aop_dst, offset);
1856         pcop2->pcop2 = temp;
1857         
1858   return PCOP(pcop2);
1859 }
1860
1861
1862
1863 /*--------------------------------------------------------------------------------.-*/
1864 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1865 /*                  VR 030601 , adapted by Hans Dorn                                */
1866 /*--------------------------------------------------------------------------------.-*/
1867 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1868 {
1869   pCodeOpReg2 *pcop2;
1870  
1871         pcop2 = (pCodeOpReg2 *)src;
1872         pcop2->pcop2 = dst;
1873         
1874         return PCOP(pcop2);
1875 }
1876
1877
1878
1879 /*---------------------------------------------------------------------------------*/
1880 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1881 /*                     movff instruction                                           */
1882 /*---------------------------------------------------------------------------------*/
1883 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1884 {
1885   pCodeOpReg2 *pcop2;
1886
1887         if(!noalloc) {
1888                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1889                 pcop2->pcop2 = pic16_popCopyReg(dst);
1890         } else {
1891                 /* the pCodeOp may be already allocated */
1892                 pcop2 = (pCodeOpReg2 *)(src);
1893                 pcop2->pcop2 = (pCodeOp *)(dst);
1894         }
1895
1896   return PCOP(pcop2);
1897 }
1898
1899
1900 /*-----------------------------------------------------------------*/
1901 /* pic16_popGet - asm operator to pcode operator conversion              */
1902 /*-----------------------------------------------------------------*/
1903 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1904 {
1905   //char *s = buffer ;
1906   char *rs;
1907   pCodeOp *pcop;
1908
1909     FENTRY2;
1910     /* offset is greater than
1911     size then zero */
1912
1913 //    if (offset > (aop->size - 1) &&
1914 //        aop->type != AOP_LIT)
1915 //      return NULL;  //zero;
1916
1917     /* depending on type */
1918     switch (aop->type) {
1919         
1920     case AOP_R0:
1921     case AOP_R1:
1922     case AOP_DPTR:
1923     case AOP_DPTR2:
1924         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1925         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1926         assert( 0 );
1927         return NULL;
1928
1929
1930     case AOP_FSR0:
1931     case AOP_FSR2:
1932       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1933       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1934       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1935       PCOR(pcop)->r->wasUsed = 1;
1936       PCOR(pcop)->r->isFree = 0;
1937       
1938       PCOR(pcop)->instance = offset;
1939       pcop->type = PCOR(pcop)->r->pc_type;
1940       return (pcop);
1941
1942     case AOP_IMMD:
1943       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1944       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1945
1946     case AOP_STA:
1947       /* pCodeOp is already allocated from aopForSym */
1948         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1949         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1950           
1951       return (pcop);
1952       
1953     case AOP_ACC:
1954       {
1955         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1956
1957         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1958
1959         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1960         
1961         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1962         PCOR(pcop)->rIdx = rIdx;
1963         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1964         PCOR(pcop)->r->wasUsed=1;
1965         PCOR(pcop)->r->isFree=0;
1966
1967         PCOR(pcop)->instance = offset;
1968         pcop->type = PCOR(pcop)->r->pc_type;
1969 //      rs = aop->aopu.aop_reg[offset]->name;
1970 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1971         return pcop;
1972
1973
1974 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1975 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1976
1977 //      assert( 0 );
1978       }
1979         
1980     case AOP_DIR:
1981       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1982       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1983         
1984 #if 0
1985     case AOP_PAGED:
1986       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1987       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1988 #endif
1989
1990     case AOP_REG:
1991       {
1992         int rIdx;
1993         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1994         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1995
1996         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1997         
1998         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1999 //      pcop->type = PO_GPR_REGISTER;
2000         PCOR(pcop)->rIdx = rIdx;
2001         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2002         PCOR(pcop)->r->wasUsed=1;
2003         PCOR(pcop)->r->isFree=0;
2004
2005         PCOR(pcop)->instance = offset;
2006         pcop->type = PCOR(pcop)->r->pc_type;
2007         
2008         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2009         rs = aop->aopu.aop_reg[offset]->name;
2010         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2011         return pcop;
2012       }
2013
2014     case AOP_CRY:
2015         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2016
2017       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2018       PCOR(pcop)->instance = offset;
2019       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2020       //if(PCOR(pcop)->r == NULL)
2021       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2022       return pcop;
2023         
2024     case AOP_LIT:
2025         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2026       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2027
2028     case AOP_STR:
2029       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2030       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2031
2032       /*
2033       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2035       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2036       pcop->type = PCOR(pcop)->r->pc_type;
2037       pcop->name = PCOR(pcop)->r->name;
2038
2039       return pcop;
2040       */
2041
2042     case AOP_PCODE:
2043       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2044                           __LINE__, 
2045                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2046       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2047       switch( aop->aopu.pcop->type ) {
2048         case PO_DIR: PCOR(pcop)->instance += offset; break;
2049         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2050         default:
2051           assert( 0 );  /* should never reach here */;
2052       }
2053       return pcop;
2054     }
2055
2056     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2057            "pic16_popGet got unsupported aop->type");
2058     exit(0);
2059 }
2060 /*-----------------------------------------------------------------*/
2061 /* pic16_aopPut - puts a string for a aop                                */
2062 /*-----------------------------------------------------------------*/
2063 void pic16_aopPut (asmop *aop, char *s, int offset)
2064 {
2065     char *d = buffer ;
2066     symbol *lbl ;
2067
2068     return;
2069
2070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071
2072     if (aop->size && offset > ( aop->size - 1)) {
2073         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2074                "pic16_aopPut got offset > aop->size");
2075         exit(0);
2076     }
2077
2078     /* will assign value to value */
2079     /* depending on where it is ofcourse */
2080     switch (aop->type) {
2081     case AOP_DIR:
2082       if (offset) {
2083         sprintf(d,"(%s + %d)",
2084                 aop->aopu.aop_dir,offset);
2085         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2086
2087       } else
2088             sprintf(d,"%s",aop->aopu.aop_dir);
2089         
2090         if (strcmp(d,s)) {
2091           DEBUGpic16_emitcode(";","%d",__LINE__);
2092           if(strcmp(s,"W"))
2093             pic16_emitcode("movf","%s,w",s);
2094           pic16_emitcode("movwf","%s",d);
2095
2096           if(strcmp(s,"W")) {
2097             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2098             if(offset >= aop->size) {
2099               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2100               break;
2101             } else
2102               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2103           }
2104
2105           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2106
2107
2108         }
2109         break;
2110         
2111     case AOP_REG:
2112       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2113         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2114           /*
2115             if (*s == '@'           ||
2116                 strcmp(s,"r0") == 0 ||
2117                 strcmp(s,"r1") == 0 ||
2118                 strcmp(s,"r2") == 0 ||
2119                 strcmp(s,"r3") == 0 ||
2120                 strcmp(s,"r4") == 0 ||
2121                 strcmp(s,"r5") == 0 ||
2122                 strcmp(s,"r6") == 0 || 
2123                 strcmp(s,"r7") == 0 )
2124                 pic16_emitcode("mov","%s,%s  ; %d",
2125                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2126             else
2127           */
2128
2129           if(strcmp(s,"W")==0 )
2130             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2131
2132           pic16_emitcode("movwf","%s",
2133                    aop->aopu.aop_reg[offset]->name);
2134
2135           if(strcmp(s,zero)==0) {
2136             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2137
2138           } else if(strcmp(s,"W")==0) {
2139             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2140             pcop->type = PO_GPR_REGISTER;
2141
2142             PCOR(pcop)->rIdx = -1;
2143             PCOR(pcop)->r = NULL;
2144
2145             DEBUGpic16_emitcode(";","%d",__LINE__);
2146             pcop->name = Safe_strdup(s);
2147             pic16_emitpcode(POC_MOVFW,pcop);
2148             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2149           } else if(strcmp(s,one)==0) {
2150             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2151             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2152           } else {
2153             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2154           }
2155         }
2156         break;
2157         
2158     case AOP_DPTR:
2159     case AOP_DPTR2:
2160     
2161     if (aop->type == AOP_DPTR2)
2162     {
2163         genSetDPTR(1);
2164     }
2165     
2166         if (aop->code) {
2167             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2168                    "pic16_aopPut writting to code space");
2169             exit(0);
2170         }
2171         
2172         while (offset > aop->coff) {
2173             aop->coff++;
2174             pic16_emitcode ("inc","dptr");
2175         }
2176         
2177         while (offset < aop->coff) {
2178             aop->coff-- ;
2179             pic16_emitcode("lcall","__decdptr");
2180         }
2181         
2182         aop->coff = offset;
2183         
2184         /* if not in accumulater */
2185         MOVA(s);        
2186         
2187         pic16_emitcode ("movx","@dptr,a");
2188         
2189     if (aop->type == AOP_DPTR2)
2190     {
2191         genSetDPTR(0);
2192     }
2193         break;
2194         
2195     case AOP_R0:
2196     case AOP_R1:
2197         while (offset > aop->coff) {
2198             aop->coff++;
2199             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2200         }
2201         while (offset < aop->coff) {
2202             aop->coff-- ;
2203             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2204         }
2205         aop->coff = offset;
2206         
2207         if (aop->paged) {
2208             MOVA(s);           
2209             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2210             
2211         } else
2212             if (*s == '@') {
2213                 MOVA(s);
2214                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2215             } else
2216                 if (strcmp(s,"r0") == 0 ||
2217                     strcmp(s,"r1") == 0 ||
2218                     strcmp(s,"r2") == 0 ||
2219                     strcmp(s,"r3") == 0 ||
2220                     strcmp(s,"r4") == 0 ||
2221                     strcmp(s,"r5") == 0 ||
2222                     strcmp(s,"r6") == 0 || 
2223                     strcmp(s,"r7") == 0 ) {
2224                     char buffer[10];
2225                     sprintf(buffer,"a%s",s);
2226                     pic16_emitcode("mov","@%s,%s",
2227                              aop->aopu.aop_ptr->name,buffer);
2228                 } else
2229                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2230         
2231         break;
2232         
2233     case AOP_STK:
2234         if (strcmp(s,"a") == 0)
2235             pic16_emitcode("push","acc");
2236         else
2237             pic16_emitcode("push","%s",s);
2238         
2239         break;
2240         
2241     case AOP_CRY:
2242         /* if bit variable */
2243         if (!aop->aopu.aop_dir) {
2244             pic16_emitcode("clr","a");
2245             pic16_emitcode("rlc","a");
2246         } else {
2247             if (s == zero) 
2248                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2249             else
2250                 if (s == one)
2251                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2252                 else
2253                     if (!strcmp(s,"c"))
2254                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2255                     else {
2256                         lbl = newiTempLabel(NULL);
2257                         
2258                         if (strcmp(s,"a")) {
2259                             MOVA(s);
2260                         }
2261                         pic16_emitcode("clr","c");
2262                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2263                         pic16_emitcode("cpl","c");
2264                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2265                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2266                     }
2267         }
2268         break;
2269         
2270     case AOP_STR:
2271         aop->coff = offset;
2272         if (strcmp(aop->aopu.aop_str[offset],s))
2273             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2274         break;
2275         
2276     case AOP_ACC:
2277         aop->coff = offset;
2278         if (!offset && (strcmp(s,"acc") == 0))
2279             break;
2280         
2281         if (strcmp(aop->aopu.aop_str[offset],s))
2282             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2283         break;
2284
2285     default :
2286         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2287 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2288 //             "pic16_aopPut got unsupported aop->type");
2289 //      exit(0);    
2290     }    
2291
2292 }
2293
2294 /*-----------------------------------------------------------------*/
2295 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2296 /*-----------------------------------------------------------------*/
2297 void pic16_mov2w (asmop *aop, int offset)
2298 {
2299   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2300
2301   if(is_LitAOp(aop))
2302     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2303   else
2304     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2305 }
2306
2307 static void mov2f(asmop *dst, asmop *src, int offset)
2308 {
2309   if(is_LitAOp(src)) {
2310     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2311     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2312   } else {
2313     if(pic16_sameRegsOfs(src, dst, offset))return;
2314     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2315                       pic16_popGet(dst, offset)));
2316   }
2317 }
2318
2319 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2320 {
2321   if(is_LitAOp(src)) {
2322     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2323     pic16_emitpcode(POC_MOVWF, dst);
2324   } else {
2325     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2326   }
2327 }
2328
2329 void pic16_testStackOverflow(void)
2330 {
2331 #define GSTACK_TEST_NAME        "__gstack_test"
2332
2333   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2334   
2335   {
2336     symbol *sym;
2337
2338       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2339       strcpy(sym->rname, GSTACK_TEST_NAME);
2340       checkAddSym(&externs, sym);
2341   }
2342
2343 }
2344
2345 /* push pcop into stack */
2346 void pic16_pushpCodeOp(pCodeOp *pcop)
2347 {
2348 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2349   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2350   if(pic16_options.gstack)
2351     pic16_testStackOverflow();
2352     
2353 }
2354
2355 /* pop pcop from stack */
2356 void pic16_poppCodeOp(pCodeOp *pcop)
2357 {
2358   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2359   if(pic16_options.gstack)
2360     pic16_testStackOverflow();
2361 }
2362
2363
2364 /*-----------------------------------------------------------------*/
2365 /* pushw - pushes wreg to stack                                    */
2366 /*-----------------------------------------------------------------*/
2367 void pushw(void)
2368 {
2369   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2370   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2371   if(pic16_options.gstack)
2372     pic16_testStackOverflow();
2373 }
2374
2375                 
2376 /*-----------------------------------------------------------------*/
2377 /* pushaop - pushes aop to stack                                   */
2378 /*-----------------------------------------------------------------*/
2379 void pushaop(asmop *aop, int offset)
2380 {
2381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2382
2383   if(is_LitAOp(aop)) {
2384     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2385     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2386   } else {
2387     pic16_emitpcode(POC_MOVFF,
2388       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2389   }
2390
2391   if(pic16_options.gstack)
2392     pic16_testStackOverflow();
2393 }
2394
2395 /*-----------------------------------------------------------------*/
2396 /* popaop - pops aop from stack                                    */
2397 /*-----------------------------------------------------------------*/
2398 void popaop(asmop *aop, int offset)
2399 {
2400   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2401   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2402   if(pic16_options.gstack)
2403     pic16_testStackOverflow();
2404 }
2405
2406 void popaopidx(asmop *aop, int offset, int index)
2407 {
2408   int ofs=1;
2409
2410     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2411
2412     if(STACK_MODEL_LARGE)ofs++;
2413
2414     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2415     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2416     if(pic16_options.gstack)
2417       pic16_testStackOverflow();
2418 }
2419
2420 #if !(USE_GENERIC_SIGNED_SHIFT)
2421 /*-----------------------------------------------------------------*/
2422 /* reAdjustPreg - points a register back to where it should        */
2423 /*-----------------------------------------------------------------*/
2424 static void reAdjustPreg (asmop *aop)
2425 {
2426     int size ;
2427
2428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2429     aop->coff = 0;
2430     if ((size = aop->size) <= 1)
2431         return ;
2432     size-- ;
2433     switch (aop->type) {
2434         case AOP_R0 :
2435         case AOP_R1 :
2436             while (size--)
2437                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2438             break;          
2439         case AOP_DPTR :
2440         case AOP_DPTR2:
2441             if (aop->type == AOP_DPTR2)
2442             {
2443                 genSetDPTR(1);
2444             } 
2445             while (size--)
2446             {
2447                 pic16_emitcode("lcall","__decdptr");
2448             }
2449                 
2450             if (aop->type == AOP_DPTR2)
2451             {
2452                 genSetDPTR(0);
2453             }                
2454             break;  
2455
2456     }   
2457
2458 }
2459 #endif
2460
2461 #if 0
2462 /*-----------------------------------------------------------------*/
2463 /* opIsGptr: returns non-zero if the passed operand is             */   
2464 /* a generic pointer type.                                         */
2465 /*-----------------------------------------------------------------*/ 
2466 static int opIsGptr(operand *op)
2467 {
2468     sym_link *type = operandType(op);
2469     
2470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2471     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2472     {
2473         return 1;
2474     }
2475     return 0;        
2476 }
2477 #endif
2478
2479 /*-----------------------------------------------------------------*/
2480 /* pic16_getDataSize - get the operand data size                         */
2481 /*-----------------------------------------------------------------*/
2482 int pic16_getDataSize(operand *op)
2483 {
2484     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2485
2486
2487     return AOP_SIZE(op);
2488
2489     // tsd- in the pic port, the genptr size is 1, so this code here
2490     // fails. ( in the 8051 port, the size was 4).
2491 #if 0
2492     int size;
2493     size = AOP_SIZE(op);
2494     if (size == GPTRSIZE)
2495     {
2496         sym_link *type = operandType(op);
2497         if (IS_GENPTR(type))
2498         {
2499             /* generic pointer; arithmetic operations
2500              * should ignore the high byte (pointer type).
2501              */
2502             size--;
2503     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2504         }
2505     }
2506     return size;
2507 #endif
2508 }
2509
2510 /*-----------------------------------------------------------------*/
2511 /* pic16_outAcc - output Acc                                             */
2512 /*-----------------------------------------------------------------*/
2513 void pic16_outAcc(operand *result)
2514 {
2515   int size,offset;
2516   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2517   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2518
2519
2520   size = pic16_getDataSize(result);
2521   if(size){
2522     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2523     size--;
2524     offset = 1;
2525     /* unsigned or positive */
2526     while(size--)
2527       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2528   }
2529
2530 }
2531
2532 /*-----------------------------------------------------------------*/
2533 /* pic16_outBitC - output a bit C                                  */
2534 /*                 Move to result the value of Carry flag -- VR    */
2535 /*-----------------------------------------------------------------*/
2536 void pic16_outBitC(operand *result)
2537 {
2538   int i;
2539
2540     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2541
2542     /* if the result is bit */
2543     if (AOP_TYPE(result) == AOP_CRY) {
2544         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2545         pic16_aopPut(AOP(result),"c",0);
2546     } else {
2547
2548         i = AOP_SIZE(result);
2549         while(i--) {
2550                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2551         }
2552         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2553     }
2554 }
2555
2556 /*-----------------------------------------------------------------*/
2557 /* pic16_outBitOp - output a bit from Op                           */
2558 /*                 Move to result the value of set/clr op -- VR    */
2559 /*-----------------------------------------------------------------*/
2560 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2561 {
2562   int i;
2563
2564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2565
2566     /* if the result is bit */
2567     if (AOP_TYPE(result) == AOP_CRY) {
2568         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2569         pic16_aopPut(AOP(result),"c",0);
2570     } else {
2571
2572         i = AOP_SIZE(result);
2573         while(i--) {
2574                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2575         }
2576         pic16_emitpcode(POC_RRCF, pcop);          
2577         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2578     }
2579 }
2580
2581 /*-----------------------------------------------------------------*/
2582 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2583 /*-----------------------------------------------------------------*/
2584 void pic16_toBoolean(operand *oper)
2585 {
2586     int size = AOP_SIZE(oper) - 1;
2587     int offset = 1;
2588
2589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2590
2591     if ( AOP_TYPE(oper) != AOP_ACC) {
2592       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2593     }
2594     while (size--) {
2595       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2596     }
2597 }
2598
2599
2600 #if !defined(GEN_Not)
2601 /*-----------------------------------------------------------------*/
2602 /* genNot - generate code for ! operation                          */
2603 /*-----------------------------------------------------------------*/
2604 static void pic16_genNot (iCode *ic)
2605 {
2606   symbol *tlbl;
2607   int size;
2608
2609   FENTRY;
2610   /* assign asmOps to operand & result */
2611   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2612   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2613
2614   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2615   /* if in bit space then a special case */
2616   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2617     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2618       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2619       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2620     } else {
2621       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2622       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2623       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2624     }
2625     goto release;
2626   }
2627
2628   size = AOP_SIZE(IC_LEFT(ic));
2629   if(size == 1) {
2630     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2632     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2633     goto release;
2634   }
2635   pic16_toBoolean(IC_LEFT(ic));
2636
2637   tlbl = newiTempLabel(NULL);
2638   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2639   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2640   pic16_outBitC(IC_RESULT(ic));
2641
2642  release:    
2643   /* release the aops */
2644   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2645   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2646 }
2647 #endif
2648
2649
2650 #if !defined(GEN_Cpl)
2651 /*-----------------------------------------------------------------*/
2652 /* genCpl - generate code for complement                           */
2653 /*-----------------------------------------------------------------*/
2654 static void pic16_genCpl (iCode *ic)
2655 {
2656   int offset = 0;
2657   int size ;
2658
2659     FENTRY;
2660     /* assign asmOps to operand & result */
2661     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2662     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2663
2664     /* if both are in bit space then 
2665     a special case */
2666     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2667         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2668
2669         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2670         pic16_emitcode("cpl","c"); 
2671         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2672         goto release; 
2673     } 
2674
2675     size = AOP_SIZE(IC_RESULT(ic));
2676     while (size--) {
2677 /*
2678         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2679         MOVA(l);       
2680         pic16_emitcode("cpl","a");
2681         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2682 */
2683         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2684               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2685         } else {
2686                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2687                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2688         }
2689         offset++;
2690
2691     }
2692
2693
2694 release:
2695     /* release the aops */
2696     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2697     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2698 }
2699 #endif
2700
2701 /*-----------------------------------------------------------------*/
2702 /* genUminusFloat - unary minus for floating points                */
2703 /*-----------------------------------------------------------------*/
2704 static void genUminusFloat(operand *op,operand *result)
2705 {
2706   int size ,offset =0 ;
2707   
2708     FENTRY;
2709     /* for this we just need to flip the 
2710     first it then copy the rest in place */
2711     size = AOP_SIZE(op);
2712
2713     while(size--) {
2714       mov2f(AOP(result), AOP(op), offset);
2715       offset++;
2716     }
2717     
2718     /* toggle the MSB's highest bit */
2719     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2720 }
2721
2722 /*-----------------------------------------------------------------*/
2723 /* genUminus - unary minus code generation                         */
2724 /*-----------------------------------------------------------------*/
2725 static void genUminus (iCode *ic)
2726 {
2727   int size, i;
2728   sym_link *optype, *rtype;
2729   symbol *label;
2730   int needLabel=0;
2731
2732     FENTRY;     
2733     
2734     /* assign asmops */
2735     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2736     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2737
2738     /* if both in bit space then special case */
2739     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2740       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2741         
2742         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2743         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2744         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2745         goto release; 
2746     } 
2747
2748     optype = operandType(IC_LEFT(ic));
2749     rtype = operandType(IC_RESULT(ic));
2750
2751     /* if float then do float stuff */
2752     if (IS_FLOAT(optype)) {
2753       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2754       goto release;
2755     }
2756
2757     /* otherwise subtract from zero by taking the 2's complement */
2758     size = AOP_SIZE(IC_LEFT(ic));
2759     label = newiTempLabel ( NULL );
2760     
2761     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2762       for (i=size-1; i > 0; i--) {
2763         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2764       } // for
2765       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2766       for (i=1; i < size; i++) {
2767         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2768         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2769       } // for
2770     } else {
2771       for (i=size-1; i >= 0; i--) {
2772         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2773         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2774       } // for
2775       if (size > 1) {
2776         for (i=0; i < size-2; i++) {
2777           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2778           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2779         } // for
2780         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2781       } // if
2782       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2783     }
2784     if (needLabel)
2785       pic16_emitpLabel (label->key);
2786
2787 release:
2788     /* release the aops */
2789     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2790     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2791 }
2792
2793 #if 0
2794 /*-----------------------------------------------------------------*/
2795 /* saveRegisters - will look for a call and save the registers     */
2796 /*-----------------------------------------------------------------*/
2797 static void saveRegisters(iCode *lic) 
2798 {
2799     int i;
2800     iCode *ic;
2801     bitVect *rsave;
2802     sym_link *dtype;
2803
2804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2805     /* look for call */
2806     for (ic = lic ; ic ; ic = ic->next) 
2807         if (ic->op == CALL || ic->op == PCALL)
2808             break;
2809
2810     if (!ic) {
2811         fprintf(stderr,"found parameter push with no function call\n");
2812         return ;
2813     }
2814
2815     /* if the registers have been saved already then
2816     do nothing */
2817     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2818         return ;
2819
2820     /* find the registers in use at this time 
2821     and push them away to safety */
2822     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2823                           ic->rUsed);
2824
2825     ic->regsSaved = 1;
2826     if (options.useXstack) {
2827         if (bitVectBitValue(rsave,R0_IDX))
2828             pic16_emitcode("mov","b,r0");
2829         pic16_emitcode("mov","r0,%s",spname);
2830         for (i = 0 ; i < pic16_nRegs ; i++) {
2831             if (bitVectBitValue(rsave,i)) {
2832                 if (i == R0_IDX)
2833                     pic16_emitcode("mov","a,b");
2834                 else
2835                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2836                 pic16_emitcode("movx","@r0,a");
2837                 pic16_emitcode("inc","r0");
2838             }
2839         }
2840         pic16_emitcode("mov","%s,r0",spname);
2841         if (bitVectBitValue(rsave,R0_IDX))
2842             pic16_emitcode("mov","r0,b");           
2843     }// else
2844     //for (i = 0 ; i < pic16_nRegs ; i++) {
2845     //    if (bitVectBitValue(rsave,i))
2846     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2847     //}
2848
2849     dtype = operandType(IC_LEFT(ic));
2850     if (currFunc && dtype && 
2851         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2852         IFFUNC_ISISR(currFunc->type) &&
2853         !ic->bankSaved) 
2854
2855         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2856
2857 }
2858 /*-----------------------------------------------------------------*/
2859 /* unsaveRegisters - pop the pushed registers                      */
2860 /*-----------------------------------------------------------------*/
2861 static void unsaveRegisters (iCode *ic)
2862 {
2863     int i;
2864     bitVect *rsave;
2865
2866     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2867     /* find the registers in use at this time 
2868     and push them away to safety */
2869     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2870                           ic->rUsed);
2871     
2872     if (options.useXstack) {
2873         pic16_emitcode("mov","r0,%s",spname);   
2874         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2875             if (bitVectBitValue(rsave,i)) {
2876                 pic16_emitcode("dec","r0");
2877                 pic16_emitcode("movx","a,@r0");
2878                 if (i == R0_IDX)
2879                     pic16_emitcode("mov","b,a");
2880                 else
2881                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2882             }       
2883
2884         }
2885         pic16_emitcode("mov","%s,r0",spname);
2886         if (bitVectBitValue(rsave,R0_IDX))
2887             pic16_emitcode("mov","r0,b");
2888     } //else
2889     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2890     //    if (bitVectBitValue(rsave,i))
2891     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2892     //}
2893
2894 }  
2895 #endif
2896
2897 #if 0  // patch 14
2898 /*-----------------------------------------------------------------*/
2899 /* pushSide -                                                      */
2900 /*-----------------------------------------------------------------*/
2901 static void pushSide(operand * oper, int size)
2902 {
2903         int offset = 0;
2904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2905         while (size--) {
2906                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2907                 if (AOP_TYPE(oper) != AOP_REG &&
2908                     AOP_TYPE(oper) != AOP_DIR &&
2909                     strcmp(l,"a") ) {
2910                         pic16_emitcode("mov","a,%s",l);
2911                         pic16_emitcode("push","acc");
2912                 } else
2913                         pic16_emitcode("push","%s",l);
2914         }
2915 }
2916 #endif // patch 14
2917
2918 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2919 {
2920   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2921     pic16_emitpcode(POC_MOVFW, src);
2922     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2923   } else {
2924     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2925         src, pic16_popGet(AOP(op), offset)));
2926   }
2927 }
2928
2929
2930 /*-----------------------------------------------------------------*/
2931 /* assignResultValue - assign results to oper, rescall==1 is       */
2932 /*                     called from genCall() or genPcall()         */
2933 /*-----------------------------------------------------------------*/
2934 static void assignResultValue(operand * oper, int rescall)
2935 {
2936   int size = AOP_SIZE(oper);
2937   int offset=0;
2938   
2939     FENTRY2;
2940 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2941     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2942
2943     if(rescall) {
2944       /* assign result from a call/pcall function() */
2945                 
2946       /* function results are stored in a special order,
2947        * see top of file with Function return policy, or manual */
2948
2949       if(size <= 4) {
2950         /* 8-bits, result in WREG */
2951         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2952                         
2953         if(size>1) {
2954           /* 16-bits, result in PRODL:WREG */
2955           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2956         }
2957                         
2958         if(size>2) {
2959           /* 24-bits, result in PRODH:PRODL:WREG */
2960           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2961         }
2962                         
2963         if(size>3) {
2964           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2965           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2966         }
2967       
2968       } else {
2969         /* >32-bits, result on stack, and FSR0 points to beginning.
2970          * Fix stack when done */
2971         /* FIXME FIXME */
2972 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2973         while (size--) {
2974 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2975 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2976                 
2977           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2978           GpsuedoStkPtr++;
2979         }
2980                         
2981         /* fix stack */
2982         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2983         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2984         if(STACK_MODEL_LARGE) {
2985           emitSKPNC;
2986           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2987         }
2988       }                 
2989     } else {
2990       int areg = 0;             /* matching argument register */
2991       
2992 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2993       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2994
2995
2996       /* its called from genReceive (probably) -- VR */
2997       /* I hope this code will not be called from somewhere else in the future! 
2998        * We manually set the pseudo stack pointer in genReceive. - dw
2999        */
3000       if(!GpsuedoStkPtr && _G.useWreg) {
3001 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3002
3003         /* The last byte in the assignment is in W */
3004         if(areg <= GpsuedoStkPtr) {
3005           size--;
3006           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3007           offset++;
3008 //          debugf("receive from WREG\n", 0);
3009         }
3010         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3011       }
3012 //      GpsuedoStkPtr++;
3013       _G.stack_lat = AOP_SIZE(oper)-1;
3014
3015       while (size) {
3016         size--;
3017         GpsuedoStkPtr++;
3018         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3019 //        debugf("receive from STACK\n", 0);
3020         offset++;
3021       }
3022     }
3023 }
3024
3025
3026 /*-----------------------------------------------------------------*/
3027 /* genIpush - generate code for pushing this gets a little complex */
3028 /*-----------------------------------------------------------------*/
3029 static void genIpush (iCode *ic)
3030 {
3031 //  int size, offset=0;
3032
3033   FENTRY;
3034   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3035
3036   if(ic->parmPush) {
3037     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3038
3039     /* send to stack as normal */
3040     addSet(&_G.sendSet,ic);
3041 //    addSetHead(&_G.sendSet,ic);
3042     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3043   }
3044
3045         
3046 #if 0
3047     int size, offset = 0 ;
3048     char *l;
3049
3050
3051     /* if this is not a parm push : ie. it is spill push 
3052     and spill push is always done on the local stack */
3053     if (!ic->parmPush) {
3054
3055         /* and the item is spilt then do nothing */
3056         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3057             return ;
3058
3059         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3060         size = AOP_SIZE(IC_LEFT(ic));
3061         /* push it on the stack */
3062         while(size--) {
3063             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3064             if (*l == '#') {
3065                 MOVA(l);
3066                 l = "acc";
3067             }
3068             pic16_emitcode("push","%s",l);
3069         }
3070         return ;        
3071     }
3072
3073     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3074 #endif
3075 }
3076
3077 /*-----------------------------------------------------------------*/
3078 /* genIpop - recover the registers: can happen only for spilling   */
3079 /*-----------------------------------------------------------------*/
3080 static void genIpop (iCode *ic)
3081 {
3082   FENTRY;
3083   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3084 #if 0
3085     int size,offset ;
3086
3087
3088     /* if the temp was not pushed then */
3089     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3090         return ;
3091
3092     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3093     size = AOP_SIZE(IC_LEFT(ic));
3094     offset = (size-1);
3095     while (size--) 
3096         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3097                                    FALSE,TRUE));
3098
3099     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3100 #endif
3101 }
3102
3103 #if 0
3104 /*-----------------------------------------------------------------*/
3105 /* unsaverbank - restores the resgister bank from stack            */
3106 /*-----------------------------------------------------------------*/
3107 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3108 {
3109   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3110 #if 0
3111     int i;
3112     asmop *aop ;
3113     regs *r = NULL;
3114
3115     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3116     if (popPsw) {
3117         if (options.useXstack) {
3118             aop = newAsmop(0);
3119             r = getFreePtr(ic,&aop,FALSE);
3120             
3121             
3122             pic16_emitcode("mov","%s,_spx",r->name);
3123             pic16_emitcode("movx","a,@%s",r->name);
3124             pic16_emitcode("mov","psw,a");
3125             pic16_emitcode("dec","%s",r->name);
3126             
3127         }else
3128             pic16_emitcode ("pop","psw");
3129     }
3130
3131     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3132         if (options.useXstack) {       
3133             pic16_emitcode("movx","a,@%s",r->name);
3134             //pic16_emitcode("mov","(%s+%d),a",
3135             //       regspic16[i].base,8*bank+regspic16[i].offset);
3136             pic16_emitcode("dec","%s",r->name);
3137
3138         } else 
3139           pic16_emitcode("pop",""); //"(%s+%d)",
3140         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3141     }
3142
3143     if (options.useXstack) {
3144
3145         pic16_emitcode("mov","_spx,%s",r->name);
3146         pic16_freeAsmop(NULL,aop,ic,TRUE);
3147
3148     }
3149 #endif 
3150 }
3151
3152 /*-----------------------------------------------------------------*/
3153 /* saverbank - saves an entire register bank on the stack          */
3154 /*-----------------------------------------------------------------*/
3155 static void saverbank (int bank, iCode *ic, bool pushPsw)
3156 {
3157   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3158 #if 0
3159     int i;
3160     asmop *aop ;
3161     regs *r = NULL;
3162
3163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3164     if (options.useXstack) {
3165
3166         aop = newAsmop(0);
3167         r = getFreePtr(ic,&aop,FALSE);  
3168         pic16_emitcode("mov","%s,_spx",r->name);
3169
3170     }
3171
3172     for (i = 0 ; i < pic16_nRegs ;i++) {
3173         if (options.useXstack) {
3174             pic16_emitcode("inc","%s",r->name);
3175             //pic16_emitcode("mov","a,(%s+%d)",
3176             //         regspic16[i].base,8*bank+regspic16[i].offset);
3177             pic16_emitcode("movx","@%s,a",r->name);           
3178         } else 
3179           pic16_emitcode("push","");// "(%s+%d)",
3180                      //regspic16[i].base,8*bank+regspic16[i].offset);
3181     }
3182     
3183     if (pushPsw) {
3184         if (options.useXstack) {
3185             pic16_emitcode("mov","a,psw");
3186             pic16_emitcode("movx","@%s,a",r->name);     
3187             pic16_emitcode("inc","%s",r->name);
3188             pic16_emitcode("mov","_spx,%s",r->name);       
3189             pic16_freeAsmop (NULL,aop,ic,TRUE);
3190             
3191         } else
3192             pic16_emitcode("push","psw");
3193         
3194         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3195     }
3196     ic->bankSaved = 1;
3197 #endif
3198 }
3199 #endif  /* 0 */
3200
3201
3202 static int wparamCmp(void *p1, void *p2)
3203 {
3204   return (!strcmp((char *)p1, (char *)p2));
3205 }
3206
3207 int inWparamList(char *s)
3208 {
3209   return isinSetWith(wparamList, s, wparamCmp);
3210
3211
3212
3213 /*-----------------------------------------------------------------*/
3214 /* genCall - generates a call statement                            */
3215 /*-----------------------------------------------------------------*/
3216 static void genCall (iCode *ic)
3217 {
3218   sym_link *ftype;   
3219   int stackParms=0;
3220   int use_wreg=0;
3221   int inwparam=0;
3222   char *fname;
3223   
3224     FENTRY;
3225
3226     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3227     /* if caller saves & we have not saved then */
3228 //    if (!ic->regsSaved)
3229 //      saveRegisters(ic);
3230
3231         /* initialise stackParms for IPUSH pushes */
3232 //      stackParms = psuedoStkPtr;
3233 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3234     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3235     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3236
3237 #if 0
3238     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3239 #endif
3240
3241     /* if send set is not empty the assign */
3242     if (_G.sendSet) {
3243       iCode *sic;
3244       int psuedoStkPtr=-1; 
3245       int firstTimeThruLoop = 1;
3246
3247
3248         /* reverse sendSet if function is not reentrant */
3249         if(!IFFUNC_ISREENT(ftype))
3250           _G.sendSet = reverseSet(_G.sendSet);
3251
3252         /* First figure how many parameters are getting passed */
3253         stackParms = 0;
3254         use_wreg = 0;
3255         
3256         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3257           int size;
3258 //          int offset = 0;
3259
3260             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3261             size = AOP_SIZE(IC_LEFT(sic));
3262
3263             stackParms += size;
3264
3265             /* pass the last byte through WREG */
3266             if(inwparam) {
3267
3268               while (size--) {
3269                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3270                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3271                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3272
3273                 if(!firstTimeThruLoop) {
3274                   /* If this is not the first time we've been through the loop
3275                    * then we need to save the parameter in a temporary
3276                    * register. The last byte of the last parameter is
3277                    * passed in W. */
3278
3279                   pushw();
3280 //                  --psuedoStkPtr;             // sanity check
3281                   use_wreg = 1;
3282                 }
3283                 
3284                 firstTimeThruLoop=0;
3285
3286                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3287
3288 //                offset++;
3289               }
3290             } else {
3291               /* all arguments are passed via stack */
3292               use_wreg = 0;
3293
3294               while (size--) {
3295                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3296                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3297                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3298
3299 //                pushaop(AOP(IC_LEFT(sic)), size);
3300                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3301                 pushw();
3302               }
3303             }
3304
3305             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3306           }
3307
3308           if(inwparam) {
3309             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3310               pushw();  /* save last parameter to stack if functions has varargs */
3311               use_wreg = 0;
3312             } else
3313               use_wreg = 1;
3314           } else use_wreg = 0;
3315
3316           _G.stackRegSet = _G.sendSet;
3317           _G.sendSet = NULL;
3318     }
3319
3320     /* make the call */
3321     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3322
3323     GpsuedoStkPtr=0;
3324     
3325     /* if we need to assign a result value */
3326     if ((IS_ITEMP(IC_RESULT(ic))
3327           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3328               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3329         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3330
3331       _G.accInUse++;
3332       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3333       _G.accInUse--;
3334
3335       assignResultValue(IC_RESULT(ic), 1);
3336
3337       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3339                 
3340       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3341     }
3342
3343     if(!stackParms && ic->parmBytes) {
3344       stackParms = ic->parmBytes;
3345     }
3346       
3347     stackParms -= use_wreg;
3348     
3349     if(stackParms>0) {
3350       if(stackParms == 1) {
3351         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3352       } else {
3353         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3354         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3355       }
3356       if(STACK_MODEL_LARGE) {
3357         emitSKPNC;
3358         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3359       }
3360     }
3361
3362 #if 0
3363     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3364 #endif
3365
3366     /* adjust the stack for parameters if required */
3367 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3368
3369 #if 0
3370       /* if register bank was saved then pop them */
3371       if (ic->bankSaved)
3372         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3373
3374       /* if we hade saved some registers then unsave them */
3375       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3376         unsaveRegisters (ic);
3377 #endif
3378 }
3379
3380
3381
3382 /*-----------------------------------------------------------------*/
3383 /* genPcall - generates a call by pointer statement                */
3384 /*            new version, created from genCall - HJD              */
3385 /*-----------------------------------------------------------------*/
3386 static void genPcall (iCode *ic)
3387 {
3388   sym_link *ftype, *fntype;
3389   int stackParms=0;
3390   symbol *retlbl = newiTempLabel(NULL);
3391   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3392   
3393     FENTRY;
3394
3395     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3396     fntype = operandType( IC_LEFT(ic) )->next;
3397
3398     /* if send set is not empty the assign */
3399     if (_G.sendSet) {
3400       iCode *sic;
3401       int psuedoStkPtr=-1; 
3402
3403       /* reverse sendSet if function is not reentrant */
3404       if(!IFFUNC_ISREENT(fntype))
3405         _G.sendSet = reverseSet(_G.sendSet);
3406
3407       stackParms = 0;
3408       
3409       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3410         int size;
3411
3412           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3413           size = AOP_SIZE(IC_LEFT(sic));
3414           stackParms += size;
3415
3416           /* all parameters are passed via stack, since WREG is clobbered
3417            * by the calling sequence */
3418           while (size--) {
3419             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3421             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3422
3423             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3424             pushw();
3425           }
3426
3427           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3428       }
3429
3430       _G.stackRegSet = _G.sendSet;
3431       _G.sendSet = NULL;
3432     }
3433
3434     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3435
3436     // push return address
3437     // push $ on return stack, then replace with retlbl
3438
3439     pic16_emitpcodeNULLop(POC_PUSH);
3440
3441     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3442     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3443     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3444     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3445     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3446     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3447
3448     /* make the call by writing the pointer into pc */
3449     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3450     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3451
3452     // note: MOVFF to PCL not allowed
3453     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3454     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3455
3456
3457     /* return address is here: (X) */
3458     pic16_emitpLabelFORCE(retlbl->key);
3459
3460     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3461
3462     GpsuedoStkPtr=0;
3463     /* if we need assign a result value */
3464     if ((IS_ITEMP(IC_RESULT(ic))
3465           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3466               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3467         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3468
3469       _G.accInUse++;
3470       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3471       _G.accInUse--;
3472
3473       assignResultValue(IC_RESULT(ic), 1);
3474
3475       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3476               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3477                 
3478       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3479     }
3480
3481 //    stackParms -= use_wreg;
3482     
3483     if(stackParms>0) {
3484       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3485       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3486       if(STACK_MODEL_LARGE) {
3487         emitSKPNC;
3488         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3489       }
3490     }
3491 }
3492
3493 /*-----------------------------------------------------------------*/
3494 /* resultRemat - result  is rematerializable                       */
3495 /*-----------------------------------------------------------------*/
3496 static int resultRemat (iCode *ic)
3497 {
3498   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3499   if (SKIP_IC(ic) || ic->op == IFX)
3500     return 0;
3501
3502   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3503     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3504     if (sym->remat && !POINTER_SET(ic)) 
3505       return 1;
3506   }
3507
3508   return 0;
3509 }
3510
3511 #if defined(__BORLANDC__) || defined(_MSC_VER)
3512 #define STRCASECMP stricmp
3513 #else
3514 #define STRCASECMP strcasecmp
3515 #endif
3516
3517 #if 0
3518 /*-----------------------------------------------------------------*/
3519 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3520 /*-----------------------------------------------------------------*/
3521 static bool inExcludeList(char *s)
3522 {
3523   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3524     int i =0;
3525     
3526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3527     if (options.excludeRegs[i] &&
3528     STRCASECMP(options.excludeRegs[i],"none") == 0)
3529         return FALSE ;
3530
3531     for ( i = 0 ; options.excludeRegs[i]; i++) {
3532         if (options.excludeRegs[i] &&
3533         STRCASECMP(s,options.excludeRegs[i]) == 0)
3534             return TRUE;
3535     }
3536     return FALSE ;
3537 }
3538 #endif
3539
3540 /*-----------------------------------------------------------------*/
3541 /* genFunction - generated code for function entry                 */
3542 /*-----------------------------------------------------------------*/
3543 static void genFunction (iCode *ic)
3544 {
3545   symbol *sym;
3546   sym_link *ftype;
3547   
3548     FENTRY;
3549     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3550
3551     pic16_labelOffset += (max_key+4);
3552     max_key=0;
3553     GpsuedoStkPtr=0;
3554     _G.nRegsSaved = 0;
3555         
3556     ftype = operandType(IC_LEFT(ic));
3557     sym = OP_SYMBOL(IC_LEFT(ic));
3558
3559     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3560       /* create an absolute section at the interrupt vector:
3561        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3562       symbol *asym;
3563       char asymname[128];
3564       pBlock *apb;
3565
3566         {
3567           int i, found=-1;
3568
3569             sym = OP_SYMBOL( IC_LEFT(ic));
3570             for(i=0;i<=2;i++) {
3571               if(interrupts[i]->name
3572                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3573                   found = i;
3574                   break;
3575               }
3576             }
3577                         
3578             if(found == -1) {
3579               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3580                             __FILE__, __LINE__, sym->name);
3581               assert( 0 );
3582             }
3583             _G.interruptvector = found;
3584         }
3585
3586         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3587         asym = newSymbol(asymname, 0);
3588
3589         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3590         pic16_addpBlock( apb );
3591
3592         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3593         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3594         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3595                 
3596         /* mark the end of this tiny function */
3597         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3598
3599         {
3600           absSym *abSym;
3601
3602             abSym = Safe_calloc(1, sizeof(absSym));
3603             strcpy(abSym->name, asymname);
3604
3605             switch( _G.interruptvector ) {
3606               case 0: abSym->address = 0x000000; break;
3607               case 1: abSym->address = 0x000008; break;
3608               case 2: abSym->address = 0x000018; break;
3609             }
3610
3611             /* relocate interrupt vectors if needed */
3612             abSym->address += pic16_options.ivt_loc;
3613
3614             addSet(&absSymSet, abSym);
3615         }
3616     }
3617
3618     /* create the function header */
3619     pic16_emitcode(";","-----------------------------------------");
3620     pic16_emitcode(";"," function %s",sym->name);
3621     pic16_emitcode(";","-----------------------------------------");
3622
3623     pic16_emitcode("","%s:",sym->rname);
3624     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3625
3626
3627     {
3628       absSym *ab;
3629
3630         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3631           if(!strcmp(ab->name, sym->rname)) {
3632             pic16_pBlockConvert2Absolute(pb);
3633             break;
3634           }
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     _G.fregsUsed = sym->regsUsed;
3650
3651     /* if this is an interrupt service routine then
3652      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3653     if (IFFUNC_ISISR(sym->type)) {
3654         _G.usefastretfie = 1;   /* use shadow registers by default */
3655         
3656         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3657         if(!(_G.interruptvector == 1)) {
3658           /* do not save WREG,STATUS,BSR for high priority interrupts
3659            * because they are stored in the hardware shadow registers already */
3660           _G.usefastretfie = 0;
3661           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3662           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3663           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3664         }
3665
3666         /* these should really be optimized somehow, because not all
3667          * interrupt handlers modify them */
3668         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3669         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3670         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3671         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3672         
3673 //        pic16_pBlockConvert2ISR(pb);
3674                 
3675     }
3676
3677     /* emit code to setup stack frame if user enabled,
3678      * and function is not main() */
3679          
3680     //fprintf(stderr, "function name: %s\n", sym->name);
3681     if(strcmp(sym->name, "main")) {
3682       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3683         /* setup the stack frame */
3684         if(STACK_MODEL_LARGE)
3685           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3686         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3687
3688         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3689         if(STACK_MODEL_LARGE)
3690           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3691       }
3692     }
3693
3694     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3695           && sym->stack) {
3696
3697       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3698
3699       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3700       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3701       emitSKPC;
3702       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3703     }
3704           
3705     if(inWparamList(sym->name)) {
3706       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3707         _G.useWreg = 0;
3708       else
3709         _G.useWreg = 1;
3710     } else
3711       _G.useWreg = 0;
3712
3713     /* if callee-save to be used for this function
3714      * then save the registers being used in this function */
3715 //    if (IFFUNC_CALLEESAVES(sym->type))
3716     {
3717       int i;
3718
3719         /* if any registers used */
3720         if (sym->regsUsed) {
3721           /* save the registers used */
3722           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3723           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3724           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3725             if (bitVectBitValue(sym->regsUsed,i)) {
3726               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3727               _G.nRegsSaved++;
3728
3729               if(!pic16_regWithIdx(i)->wasUsed) {
3730                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3731                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3732                 pic16_regWithIdx(i)->wasUsed = 1;
3733               }
3734             }
3735           }
3736           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3737         }
3738     }
3739         
3740     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3741 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3742 }
3743
3744 /*-----------------------------------------------------------------*/
3745 /* genEndFunction - generates epilogue for functions               */
3746 /*-----------------------------------------------------------------*/
3747 static void genEndFunction (iCode *ic)
3748 {
3749   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3750
3751     FENTRY;
3752
3753     if(IFFUNC_ISNAKED(sym->type)) {
3754       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3755       return;
3756     }
3757
3758     _G.stack_lat = 0;
3759
3760     /* add code for ISCRITICAL */
3761     if(IFFUNC_ISCRITICAL(sym->type)) {
3762       /* if critical function, turn on interrupts */
3763       
3764       /* TODO: add code here -- VR */
3765     }
3766     
3767 //    sym->regsUsed = _G.fregsUsed;
3768     
3769     /* now we need to restore the registers */
3770     /* if any registers used */
3771     if (sym->regsUsed) {
3772       int i;
3773
3774         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3775         /* restore registers used */
3776         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3777         for ( i = sym->regsUsed->size; i >= 0; i--) {
3778           if (bitVectBitValue(sym->regsUsed,i)) {
3779             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3780             _G.nRegsSaved--;
3781           }
3782         }
3783         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3784
3785     }
3786
3787     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3788           && sym->stack) {
3789       if (sym->stack == 1) {
3790         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3791         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3792       } else {
3793         // we have to add more than one...
3794         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3795         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3796         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3797         emitSKPNC;
3798         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3799         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3800         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3801       }
3802     }
3803
3804     if(strcmp(sym->name, "main")) {
3805       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3806         /* restore stack frame */
3807         if(STACK_MODEL_LARGE)
3808           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3809         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3810       }
3811     }
3812
3813     _G.useWreg = 0;
3814
3815     if (IFFUNC_ISISR(sym->type)) {
3816       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3817       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3818       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3819       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3820
3821       if(!(_G.interruptvector == 1)) {
3822         /* do not restore interrupt vector for WREG,STATUS,BSR
3823          * for high priority interrupt, see genFunction */
3824         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3825         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3826         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3827       }
3828       _G.interruptvector = 0;           /* sanity check */
3829
3830
3831       /* if debug then send end of function */
3832 /*      if (options.debug && currFunc)  */
3833       if (currFunc) {
3834         debugFile->writeEndFunction (currFunc, ic, 1);
3835       }
3836         
3837       if(_G.usefastretfie)
3838         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3839       else
3840         pic16_emitpcodeNULLop(POC_RETFIE);
3841
3842       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3843       
3844       _G.usefastretfie = 0;
3845       return;
3846     }
3847
3848     if (IFFUNC_ISCRITICAL(sym->type)) {
3849       pic16_emitcode("setb","ea");
3850     }
3851
3852     /* if debug then send end of function */
3853     if (currFunc) {
3854       debugFile->writeEndFunction (currFunc, ic, 1);
3855     }
3856
3857     /* insert code to restore stack frame, if user enabled it
3858      * and function is not main() */
3859          
3860
3861     pic16_emitpcodeNULLop(POC_RETURN);
3862
3863     /* Mark the end of a function */
3864     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3865 }
3866
3867
3868 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3869 {
3870   if(is_LitOp(op)) {
3871     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3872       if(lit == 0) {
3873         pic16_emitpcode(POC_CLRF, dest);
3874       } else {
3875         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3876         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3877       }
3878   } else {
3879     if(dest->type == PO_WREG && (offset == 0)) {
3880       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3881       return;
3882     }
3883     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3884   }
3885 }
3886
3887 /*-----------------------------------------------------------------*/
3888 /* genRet - generate code for return statement                     */
3889 /*-----------------------------------------------------------------*/
3890 static void genRet (iCode *ic)
3891 {
3892   int size;
3893   operand *left;
3894
3895     FENTRY;
3896         /* if we have no return value then
3897          * just generate the "ret" */
3898         
3899         if (!IC_LEFT(ic)) 
3900                 goto jumpret;       
3901     
3902         /* we have something to return then
3903          * move the return value into place */
3904         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3905         size = AOP_SIZE(IC_LEFT(ic));
3906
3907         if(size <= 4) {
3908                 if(size>3) {
3909                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3910 //                      pic16_emitpcode(POC_MOVFF,
3911 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3912                 }
3913                 if(size>2) {
3914                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3915 //                      pic16_emitpcode(POC_MOVFF,
3916 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3917                 }
3918                 if(size>1) {
3919                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3920 //                      pic16_emitpcode(POC_MOVFF,
3921 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3922                 }
3923
3924 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3925
3926                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3927 //              pic16_emitpcode(POC_MOVFF,
3928 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3929
3930         } else {
3931                 /* >32-bits, setup stack and FSR0 */
3932                 while (size--) {
3933 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3934 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3935
3936                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3937
3938 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3939                         GpsuedoStkPtr++;
3940                 }
3941                         
3942                 /* setup FSR0 */
3943                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3944                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3945
3946                 if(STACK_MODEL_LARGE) {
3947                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3948                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3949                 } else {
3950                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3951                 }
3952         }
3953                                 
3954 #if 0
3955         /* old code, left here for reference -- VR */    
3956         while (size--) {
3957           char *l ;
3958
3959                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3960                         /* #NOCHANGE */
3961                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3962                         pic16_emitpcomment("push %s",l);
3963                         pushed++;
3964                 } else {
3965                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3966                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3967                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3968                         
3969                         if (strcmp(fReturn[offset],l)) {
3970                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3971                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3972                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3973                                 } else {
3974                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3975                                 }
3976                                 
3977                                 if(size) {
3978                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3979                                 }
3980                                 offset++;
3981                         }
3982                 }
3983         }    
3984
3985         if (pushed) {
3986                 while(pushed) {
3987                         pushed--;
3988                         if (strcmp(fReturn[pushed],"a"))
3989                                 pic16_emitcode("pop",fReturn[pushed]);
3990                         else
3991                                 pic16_emitcode("pop","acc");
3992                 }
3993         }
3994 #endif
3995
3996
3997         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3998     
3999 jumpret:
4000         /* generate a jump to the return label
4001          * if the next is not the return statement */
4002         if (!(ic->next && ic->next->op == LABEL
4003                 && IC_LABEL(ic->next) == returnLabel)) {
4004         
4005                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4006                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4007         }
4008 }
4009
4010 /*-----------------------------------------------------------------*/
4011 /* genLabel - generates a label                                    */
4012 /*-----------------------------------------------------------------*/
4013 static void genLabel (iCode *ic)
4014 {
4015   FENTRY;
4016
4017   /* special case never generate */
4018   if (IC_LABEL(ic) == entryLabel)
4019     return ;
4020
4021   pic16_emitpLabel(IC_LABEL(ic)->key);
4022 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4023 }
4024
4025 /*-----------------------------------------------------------------*/
4026 /* genGoto - generates a goto                                      */
4027 /*-----------------------------------------------------------------*/
4028 //tsd
4029 static void genGoto (iCode *ic)
4030 {
4031   FENTRY;
4032   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4033 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4034 }
4035
4036
4037 /*-----------------------------------------------------------------*/
4038 /* genMultbits :- multiplication of bits                           */
4039 /*-----------------------------------------------------------------*/
4040 static void genMultbits (operand *left, 
4041                          operand *right, 
4042                          operand *result)
4043 {
4044   FENTRY;
4045
4046   if(!pic16_sameRegs(AOP(result),AOP(right)))
4047     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4048
4049   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4050   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4051   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4052
4053 }
4054
4055
4056 /*-----------------------------------------------------------------*/
4057 /* genMultOneByte : 8 bit multiplication & division                */
4058 /*-----------------------------------------------------------------*/
4059 static void genMultOneByte (operand *left,
4060                             operand *right,
4061                             operand *result)
4062 {
4063
4064   FENTRY;
4065   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4066   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4067
4068   /* (if two literals, the value is computed before) */
4069   /* if one literal, literal on the right */
4070   if (AOP_TYPE(left) == AOP_LIT){
4071     operand *t = right;
4072     right = left;
4073     left = t;
4074   }
4075
4076         /* size is already checked in genMult == 1 */
4077 //      size = AOP_SIZE(result);
4078
4079         if (AOP_TYPE(right) == AOP_LIT){
4080                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4081                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4082                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4083                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4084         } else {
4085                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4086                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4087                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4088                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4089         }
4090         
4091         pic16_genMult8X8_8 (left, right,result);
4092 }
4093
4094 /*-----------------------------------------------------------------*/
4095 /* genMultOneWord : 16 bit multiplication                          */
4096 /*-----------------------------------------------------------------*/
4097 static void genMultOneWord (operand *left,
4098                             operand *right,
4099                             operand *result)
4100 {
4101   FENTRY;
4102   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4103   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4104
4105   /* (if two literals, the value is computed before)
4106    * if one literal, literal on the right */
4107   if (AOP_TYPE(left) == AOP_LIT){
4108     operand *t = right;
4109     right = left;
4110     left = t;
4111   }
4112
4113   /* size is checked already == 2 */
4114 //  size = AOP_SIZE(result);
4115
4116   if (AOP_TYPE(right) == AOP_LIT) {
4117     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4118       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4119       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4120       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4121   } else {
4122     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4123       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4124       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4125       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4126   }
4127         
4128   pic16_genMult16X16_16(left, right,result);
4129 }
4130
4131 /*-----------------------------------------------------------------*/
4132 /* genMultOneLong : 32 bit multiplication                          */
4133 /*-----------------------------------------------------------------*/
4134 static void genMultOneLong (operand *left,
4135                             operand *right,
4136                             operand *result)
4137 {
4138   FENTRY;
4139   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4140   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4141
4142   /* (if two literals, the value is computed before)
4143    * if one literal, literal on the right */
4144   if (AOP_TYPE(left) == AOP_LIT){
4145     operand *t = right;
4146     right = left;
4147     left = t;
4148   }
4149
4150   /* size is checked already == 4 */
4151 //  size = AOP_SIZE(result);
4152
4153   if (AOP_TYPE(right) == AOP_LIT) {
4154     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4155         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4156         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4157         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4158   } else {
4159     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4160         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4161         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4162         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4163   }
4164         
4165   pic16_genMult32X32_32(left, right,result);
4166 }
4167
4168
4169
4170 /*-----------------------------------------------------------------*/
4171 /* genMult - generates code for multiplication                     */
4172 /*-----------------------------------------------------------------*/
4173 static void genMult (iCode *ic)
4174 {
4175   operand *left = IC_LEFT(ic);
4176   operand *right = IC_RIGHT(ic);
4177   operand *result= IC_RESULT(ic);   
4178
4179     FENTRY;
4180         /* assign the amsops */
4181         pic16_aopOp (left,ic,FALSE);
4182         pic16_aopOp (right,ic,FALSE);
4183         pic16_aopOp (result,ic,TRUE);
4184
4185         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4186
4187         /* special cases first *
4188         * both are bits */
4189         if (AOP_TYPE(left) == AOP_CRY
4190                 && AOP_TYPE(right)== AOP_CRY) {
4191                 genMultbits(left,right,result);
4192           goto release ;
4193         }
4194
4195         /* if both are of size == 1 */
4196         if(AOP_SIZE(left) == 1
4197                 && AOP_SIZE(right) == 1) {
4198                 genMultOneByte(left,right,result);
4199           goto release ;
4200         }
4201
4202         /* if both are of size == 2 */
4203         if(AOP_SIZE(left) == 2
4204                 && AOP_SIZE(right) == 2) {
4205                 genMultOneWord(left, right, result);
4206           goto release;
4207         }
4208         
4209         /* if both are of size == 4 */
4210         if(AOP_SIZE(left) == 4
4211                 && AOP_SIZE(right) == 4) {
4212                 genMultOneLong(left, right, result);
4213           goto release;
4214         }
4215         
4216         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4217
4218
4219         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4220         /* should have been converted to function call */
4221         assert(0) ;
4222
4223 release :
4224         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4225         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4226         pic16_freeAsmop(result,NULL,ic,TRUE); 
4227 }
4228
4229 /*-----------------------------------------------------------------*/
4230 /* genDivbits :- division of bits                                  */
4231 /*-----------------------------------------------------------------*/
4232 static void genDivbits (operand *left, 
4233                         operand *right, 
4234                         operand *result)
4235 {
4236   char *l;
4237
4238     FENTRY;
4239     /* the result must be bit */    
4240     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4241     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4242
4243     MOVA(l);    
4244
4245     pic16_emitcode("div","ab");
4246     pic16_emitcode("rrc","a");
4247     pic16_aopPut(AOP(result),"c",0);
4248 }
4249
4250 /*-----------------------------------------------------------------*/
4251 /* genDivOneByte : 8 bit division                                  */
4252 /*-----------------------------------------------------------------*/
4253 static void genDivOneByte (operand *left,
4254                            operand *right,
4255                            operand *result)
4256 {
4257   sym_link *opetype = operandType(result);
4258   char *l ;
4259   symbol *lbl ;
4260   int size,offset;
4261
4262         /* result = divident / divisor
4263          * - divident may be a register or a literal,
4264          * - divisor may be a register or a literal,
4265          * so there are 3 cases (literal / literal is optimized
4266          * by the front-end) to handle.
4267          * In addition we must handle signed and unsigned, which
4268          * result in 6 final different cases -- VR */
4269
4270     FENTRY;
4271     
4272     size = AOP_SIZE(result) - 1;
4273     offset = 1;
4274     /* signed or unsigned */
4275     if (SPEC_USIGN(opetype)) {
4276       pCodeOp *pct1,    /* count */
4277                 *pct2,  /* reste */
4278                 *pct3;  /* temp */
4279       symbol *label1, *label2, *label3;;
4280
4281
4282         /* unsigned is easy */
4283
4284         pct1 = pic16_popGetTempReg(1);
4285         pct2 = pic16_popGetTempReg(1);
4286         pct3 = pic16_popGetTempReg(1);
4287         
4288         label1 = newiTempLabel(NULL);
4289         label2 = newiTempLabel(NULL);
4290         label3 = newiTempLabel(NULL);
4291
4292         /* the following algorithm is extracted from divuint.c */
4293
4294         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4295         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4296         
4297         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4298
4299         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4300         
4301         pic16_emitpLabel(label1->key);
4302         
4303         emitCLRC;
4304         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4305
4306
4307         emitCLRC;
4308         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4309         
4310
4311         emitSKPNC;
4312         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4313         
4314         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4315         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4316         
4317         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4318         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4319         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4320         
4321         pic16_emitpLabel( label3->key );
4322         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4323         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4324         
4325         
4326
4327         pic16_emitpLabel(label2->key);
4328         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4329         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4330         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4331         
4332         /* result is in wreg */
4333         if(AOP_TYPE(result) != AOP_ACC)
4334                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4335
4336         pic16_popReleaseTempReg( pct3, 1);
4337         pic16_popReleaseTempReg( pct2, 1);
4338         pic16_popReleaseTempReg( pct1, 1);
4339
4340         return ;
4341     }
4342
4343     /* signed is a little bit more difficult */
4344
4345     /* save the signs of the operands */
4346     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4347     MOVA(l);    
4348     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4349     pic16_emitcode("push","acc"); /* save it on the stack */
4350
4351     /* now sign adjust for both left & right */
4352     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4353     MOVA(l);       
4354     lbl = newiTempLabel(NULL);
4355     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4356     pic16_emitcode("cpl","a");   
4357     pic16_emitcode("inc","a");
4358     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4359     pic16_emitcode("mov","b,a");
4360
4361     /* sign adjust left side */
4362     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4363     MOVA(l);
4364
4365     lbl = newiTempLabel(NULL);
4366     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4367     pic16_emitcode("cpl","a");
4368     pic16_emitcode("inc","a");
4369     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4370
4371     /* now the division */
4372     pic16_emitcode("div","ab");
4373     /* we are interested in the lower order
4374     only */
4375     pic16_emitcode("mov","b,a");
4376     lbl = newiTempLabel(NULL);
4377     pic16_emitcode("pop","acc");   
4378     /* if there was an over flow we don't 
4379     adjust the sign of the result */
4380     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4381     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4382     CLRC;
4383     pic16_emitcode("clr","a");
4384     pic16_emitcode("subb","a,b");
4385     pic16_emitcode("mov","b,a");
4386     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4387
4388     /* now we are done */
4389     pic16_aopPut(AOP(result),"b",0);
4390     if(size > 0){
4391         pic16_emitcode("mov","c,b.7");
4392         pic16_emitcode("subb","a,acc");   
4393     }
4394     while (size--)
4395         pic16_aopPut(AOP(result),"a",offset++);
4396
4397 }
4398
4399 /*-----------------------------------------------------------------*/
4400 /* genDiv - generates code for division                            */
4401 /*-----------------------------------------------------------------*/
4402 static void genDiv (iCode *ic)
4403 {
4404     operand *left = IC_LEFT(ic);
4405     operand *right = IC_RIGHT(ic);
4406     operand *result= IC_RESULT(ic);   
4407
4408
4409         /* Division is a very lengthy algorithm, so it is better
4410          * to call support routines than inlining algorithm.
4411          * Division functions written here just in case someone
4412          * wants to inline and not use the support libraries -- VR */
4413
4414     FENTRY;
4415     
4416     /* assign the amsops */
4417     pic16_aopOp (left,ic,FALSE);
4418     pic16_aopOp (right,ic,FALSE);
4419     pic16_aopOp (result,ic,TRUE);
4420
4421     /* special cases first */
4422     /* both are bits */
4423     if (AOP_TYPE(left) == AOP_CRY &&
4424         AOP_TYPE(right)== AOP_CRY) {
4425         genDivbits(left,right,result);
4426         goto release ;
4427     }
4428
4429     /* if both are of size == 1 */
4430     if (AOP_SIZE(left) == 1 &&
4431         AOP_SIZE(right) == 1 ) {
4432         genDivOneByte(left,right,result);
4433         goto release ;
4434     }
4435
4436     /* should have been converted to function call */
4437     assert(0);
4438 release :
4439     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441     pic16_freeAsmop(result,NULL,ic,TRUE); 
4442 }
4443
4444 /*-----------------------------------------------------------------*/
4445 /* genModbits :- modulus of bits                                   */
4446 /*-----------------------------------------------------------------*/
4447 static void genModbits (operand *left, 
4448                         operand *right, 
4449                         operand *result)
4450 {
4451   char *l;
4452
4453     FENTRY;  
4454     
4455     werror(W_POSSBUG2, __FILE__, __LINE__);
4456     /* the result must be bit */    
4457     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4458     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4459
4460     MOVA(l);       
4461
4462     pic16_emitcode("div","ab");
4463     pic16_emitcode("mov","a,b");
4464     pic16_emitcode("rrc","a");
4465     pic16_aopPut(AOP(result),"c",0);
4466 }
4467
4468 /*-----------------------------------------------------------------*/
4469 /* genModOneByte : 8 bit modulus                                   */
4470 /*-----------------------------------------------------------------*/
4471 static void genModOneByte (operand *left,
4472                            operand *right,
4473                            operand *result)
4474 {
4475   sym_link *opetype = operandType(result);
4476   char *l ;
4477   symbol *lbl ;
4478
4479     FENTRY;
4480     werror(W_POSSBUG2, __FILE__, __LINE__);
4481
4482     /* signed or unsigned */
4483     if (SPEC_USIGN(opetype)) {
4484         /* unsigned is easy */
4485         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4486         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4487         MOVA(l);    
4488         pic16_emitcode("div","ab");
4489         pic16_aopPut(AOP(result),"b",0);
4490         return ;
4491     }
4492
4493     /* signed is a little bit more difficult */
4494
4495     /* save the signs of the operands */
4496     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4497     MOVA(l);
4498
4499     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4500     pic16_emitcode("push","acc"); /* save it on the stack */
4501
4502     /* now sign adjust for both left & right */
4503     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4504     MOVA(l);
4505
4506     lbl = newiTempLabel(NULL);
4507     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4508     pic16_emitcode("cpl","a");   
4509     pic16_emitcode("inc","a");
4510     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4511     pic16_emitcode("mov","b,a"); 
4512
4513     /* sign adjust left side */
4514     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4515     MOVA(l);
4516
4517     lbl = newiTempLabel(NULL);
4518     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4519     pic16_emitcode("cpl","a");   
4520     pic16_emitcode("inc","a");
4521     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4522
4523     /* now the multiplication */
4524     pic16_emitcode("div","ab");
4525     /* we are interested in the lower order
4526     only */
4527     lbl = newiTempLabel(NULL);
4528     pic16_emitcode("pop","acc");   
4529     /* if there was an over flow we don't 
4530     adjust the sign of the result */
4531     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4532     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4533     CLRC ;
4534     pic16_emitcode("clr","a");
4535     pic16_emitcode("subb","a,b");
4536     pic16_emitcode("mov","b,a");
4537     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4538
4539     /* now we are done */
4540     pic16_aopPut(AOP(result),"b",0);
4541
4542 }
4543
4544 /*-----------------------------------------------------------------*/
4545 /* genMod - generates code for division                            */
4546 /*-----------------------------------------------------------------*/
4547 static void genMod (iCode *ic)
4548 {
4549   operand *left = IC_LEFT(ic);
4550   operand *right = IC_RIGHT(ic);
4551   operand *result= IC_RESULT(ic);  
4552
4553     FENTRY;
4554     
4555     /* assign the amsops */
4556     pic16_aopOp (left,ic,FALSE);
4557     pic16_aopOp (right,ic,FALSE);
4558     pic16_aopOp (result,ic,TRUE);
4559
4560     /* special cases first */
4561     /* both are bits */
4562     if (AOP_TYPE(left) == AOP_CRY &&
4563         AOP_TYPE(right)== AOP_CRY) {
4564         genModbits(left,right,result);
4565         goto release ;
4566     }
4567
4568     /* if both are of size == 1 */
4569     if (AOP_SIZE(left) == 1 &&
4570         AOP_SIZE(right) == 1 ) {
4571         genModOneByte(left,right,result);
4572         goto release ;
4573     }
4574
4575     /* should have been converted to function call */
4576     assert(0);
4577
4578 release :
4579     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4580     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4581     pic16_freeAsmop(result,NULL,ic,TRUE); 
4582 }
4583
4584 /*-----------------------------------------------------------------*/
4585 /* genIfxJump :- will create a jump depending on the ifx           */
4586 /*-----------------------------------------------------------------*/
4587 /*
4588   note: May need to add parameter to indicate when a variable is in bit space.
4589 */
4590 static void genIfxJump (iCode *ic, char *jval)
4591 {
4592   FENTRY;
4593   
4594     /* if true label then we jump if condition
4595     supplied is true */
4596     if ( IC_TRUE(ic) ) {
4597
4598         if(strcmp(jval,"a") == 0)
4599           emitSKPZ;
4600         else if (strcmp(jval,"c") == 0)
4601           emitSKPNC;
4602         else {
4603           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4604           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4605         }
4606
4607         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4608         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4609
4610     }
4611     else {
4612         /* false label is present */
4613         if(strcmp(jval,"a") == 0)
4614           emitSKPNZ;
4615         else if (strcmp(jval,"c") == 0)
4616           emitSKPC;
4617         else {
4618           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4619           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4620         }
4621
4622         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4623         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4624
4625     }
4626
4627
4628     /* mark the icode as generated */
4629     ic->generated = 1;
4630 }
4631
4632 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4633 {
4634   FENTRY;
4635   
4636     /* if true label then we jump if condition
4637     supplied is true */
4638     if ( IC_TRUE(ic) ) {
4639       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4640       pic16_emitpcode(POC_BTFSC, jop);
4641
4642       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4643       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4644
4645     } else {
4646       /* false label is present */
4647       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4648       pic16_emitpcode(POC_BTFSS, jop);
4649           
4650       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4651       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4652     }
4653
4654
4655     /* mark the icode as generated */
4656     ic->generated = 1;
4657 }
4658
4659 #if 0
4660 // not needed ATM
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genSkip                                                         */
4664 /*-----------------------------------------------------------------*/
4665 static void genSkip(iCode *ifx,int status_bit)
4666 {
4667   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4668   if(!ifx)
4669     return;
4670
4671   if ( IC_TRUE(ifx) ) {
4672     switch(status_bit) {
4673     case 'z':
4674       emitSKPNZ;
4675       break;
4676
4677     case 'c':
4678       emitSKPNC;
4679       break;
4680
4681     case 'd':
4682       emitSKPDC;
4683       break;
4684
4685     }
4686
4687     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4688     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4689
4690   } else {
4691
4692     switch(status_bit) {
4693
4694     case 'z':
4695       emitSKPZ;
4696       break;
4697
4698     case 'c':
4699       emitSKPC;
4700       break;
4701
4702     case 'd':
4703       emitSKPDC;
4704       break;
4705     }
4706     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4707     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4708
4709   }
4710
4711 }
4712 #endif
4713
4714 /*-----------------------------------------------------------------*/
4715 /* genSkipc                                                        */
4716 /*-----------------------------------------------------------------*/
4717 static void genSkipc(resolvedIfx *rifx)
4718 {
4719   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4720   
4721   if(!rifx)
4722     return;
4723
4724   if(rifx->condition)
4725     emitSKPC;
4726   else
4727     emitSKPNC;
4728
4729   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4730   rifx->generated = 1;
4731 }
4732
4733 #if !(USE_SIMPLE_GENCMP)
4734 /*-----------------------------------------------------------------*/
4735 /* genSkipz2                                                       */
4736 /*-----------------------------------------------------------------*/
4737 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4738 {
4739   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4740   
4741   if(!rifx)
4742     return;
4743
4744   if( (rifx->condition ^ invert_condition) & 1)
4745     emitSKPZ;
4746   else
4747     emitSKPNZ;
4748
4749   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4750   rifx->generated = 1;
4751 }
4752 #endif
4753
4754 #if 0
4755 /*-----------------------------------------------------------------*/
4756 /* genSkipz                                                        */
4757 /*-----------------------------------------------------------------*/
4758 static void genSkipz(iCode *ifx, int condition)
4759 {
4760   if(!ifx)
4761     return;
4762
4763   if(condition)
4764     emitSKPNZ;
4765   else
4766     emitSKPZ;
4767
4768   if ( IC_TRUE(ifx) )
4769     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4770   else
4771     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4772
4773   if ( IC_TRUE(ifx) )
4774     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4775   else
4776     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4777
4778 }
4779 #endif
4780
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4783 /* genSkipCond                                                     */
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4786 {
4787   if(!rifx)
4788     return;
4789
4790   if(rifx->condition)
4791     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4792   else
4793     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4794
4795
4796   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797   rifx->generated = 1;
4798 }
4799 #endif
4800
4801 #if 0
4802 /*-----------------------------------------------------------------*/
4803 /* genChkZeroes :- greater or less than comparison                 */
4804 /*     For each byte in a literal that is zero, inclusive or the   */
4805 /*     the corresponding byte in the operand with W                */
4806 /*     returns true if any of the bytes are zero                   */
4807 /*-----------------------------------------------------------------*/
4808 static int genChkZeroes(operand *op, int lit,  int size)
4809 {
4810
4811   int i;
4812   int flag =1;
4813
4814   while(size--) {
4815     i = (lit >> (size*8)) & 0xff;
4816
4817     if(i==0) {
4818       if(flag) 
4819         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4820       else
4821         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4822       flag = 0;
4823     }
4824   }
4825
4826   return (flag==0);
4827 }
4828 #endif
4829
4830 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4831 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4832 #endif
4833 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4834 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4835
4836 /*-----------------------------------------------------------------*/
4837 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4838 /*                  aop (if it's NOT a literal) or from lit (if    */
4839 /*                  aop is a literal)                              */
4840 /*-----------------------------------------------------------------*/
4841 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4842   if (aop->type == AOP_LIT) {
4843     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4844   } else {
4845     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4846   }
4847 }
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genCmp :- greater or less than comparison                       */
4851 /*-----------------------------------------------------------------*/
4852
4853 #if USE_SIMPLE_GENCMP
4854
4855 /* genCmp performs a left < right comparison, stores
4856  * the outcome in result (if != NULL) and generates
4857  * control flow code for the ifx (if != NULL).
4858  *
4859  * This version leaves in sequences like
4860  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4861  * which should be optmized by the peephole
4862  * optimizer - RN 2005-01-01 */
4863 static void genCmp (operand *left,operand *right,
4864                     operand *result, iCode *ifx, int sign)
4865 {
4866   resolvedIfx rIfx;
4867   int size;
4868   int offs;
4869   symbol *templbl;
4870   operand *dummy;
4871   unsigned long lit;
4872   unsigned long mask;
4873   int performedLt;
4874
4875   FENTRY;
4876   
4877   assert (AOP_SIZE(left) == AOP_SIZE(right));
4878   assert (left && right);
4879
4880   size = AOP_SIZE(right) - 1;
4881   mask = (0x100UL << (size*8)) - 1;
4882   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4883   performedLt = 1;
4884   templbl = NULL;
4885   lit = 0;
4886   
4887   resolveIfx (&rIfx, ifx);
4888
4889   /**********************************************************************
4890    * handle bits - bit compares are promoted to int compares seemingly! *
4891    **********************************************************************/
4892 #if 0
4893   // THIS IS COMPLETELY UNTESTED!
4894   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4895     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4896     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4897     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4898
4899     emitSETC;
4900     // 1 < {0,1} is false --> clear C by skipping the next instruction
4901     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4902     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4903     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4904     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4905     emitCLRC; // only skipped for left=0 && right=1
4906
4907     goto correct_result_in_carry;
4908   } // if
4909 #endif
4910
4911   /*************************************************
4912    * make sure that left is register (or the like) *
4913    *************************************************/
4914   if (!isAOP_REGlike(left)) {
4915     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4916     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4917     #endif
4918     assert (isAOP_LIT(left));
4919     assert (isAOP_REGlike(right));
4920     // swap left and right
4921     // left < right <==> right > left <==> (right >= left + 1)
4922     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4923
4924     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4925       // MAXVALUE < right? always false
4926       if (performedLt) emitCLRC; else emitSETC;
4927       goto correct_result_in_carry;
4928     } // if
4929
4930     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4931     // that's we handled it above.
4932     lit++;
4933
4934     dummy = left;
4935     left = right;
4936     right = dummy;
4937
4938     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4939   } else if (isAOP_LIT(right)) {
4940     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4941   } // if
4942
4943   assert (isAOP_REGlike(left)); // left must be register or the like
4944   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4945
4946   /*************************************************
4947    * special cases go here                         *
4948    *************************************************/
4949
4950   if (isAOP_LIT(right)) {
4951     if (!sign) {
4952       // unsigned comparison to a literal
4953       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4954       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4955       #endif
4956       if (lit == 0) {
4957         // unsigned left < 0? always false
4958         if (performedLt) emitCLRC; else emitSETC;
4959         goto correct_result_in_carry;
4960       }
4961     } else {
4962       // signed comparison to a literal
4963       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4964       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4965       #endif
4966       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4967         // signed left < 0x80000000? always false
4968         if (performedLt) emitCLRC; else emitSETC;
4969         goto correct_result_in_carry;
4970       } else if (lit == 0) {
4971         // compare left < 0; set CARRY if SIGNBIT(left) is set
4972         if (performedLt) emitSETC; else emitCLRC;
4973         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4974         if (performedLt) emitCLRC; else emitSETC;
4975         goto correct_result_in_carry;
4976       }
4977     } // if (!sign)
4978   } // right is literal
4979
4980   /*************************************************
4981    * perform a general case comparison             *
4982    * make sure we get CARRY==1 <==> left >= right  *
4983    *************************************************/
4984   // compare most significant bytes
4985   //DEBUGpc ("comparing bytes at offset %d", size);
4986   if (!sign) {
4987     // unsigned comparison
4988     mov2w_regOrLit (AOP(right), lit, size);
4989     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4990   } else {
4991     // signed comparison
4992     // (add 2^n to both operands then perform an unsigned comparison)
4993     if (isAOP_LIT(right)) {
4994       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4995       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4996
4997       if (litbyte == 0x80) {
4998         // left >= 0x80 -- always true, but more bytes to come
4999         pic16_mov2w (AOP(left), size);
5000         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5001         emitSETC;
5002       } else {
5003         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5004         pic16_mov2w (AOP(left), size);
5005         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5006         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5007       } // if
5008     } else {
5009       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5010       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5011       pic16_mov2w (AOP(left), size);
5012       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5013       pic16_emitpcode (POC_MOVWF, pctemp);
5014       pic16_mov2w (AOP(right), size);
5015       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5016       pic16_emitpcode (POC_SUBFW, pctemp);
5017       //pic16_popReleaseTempReg(pctemp, 1);
5018     }
5019   } // if (!sign)
5020
5021   // compare remaining bytes (treat as unsigned case from above)
5022   templbl = newiTempLabel ( NULL );
5023   offs = size;
5024   while (offs--) {
5025     //DEBUGpc ("comparing bytes at offset %d", offs);
5026     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5027     mov2w_regOrLit (AOP(right), lit, offs);
5028     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5029   } // while (offs)
5030   pic16_emitpLabel (templbl->key);
5031   goto result_in_carry;
5032
5033 result_in_carry:
5034   
5035   /****************************************************
5036    * now CARRY contains the result of the comparison: *
5037    * SUBWF sets CARRY iff                             *
5038    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5039    * (F=left, W=right)
5040    ****************************************************/
5041
5042   if (performedLt) {
5043     if (result && AOP_TYPE(result) != AOP_CRY) {
5044       // value will be stored
5045       emitTOGC;
5046     } else {
5047       // value wil only be used in the following genSkipc()
5048       rIfx.condition ^= 1;
5049     }
5050   } // if
5051
5052 correct_result_in_carry:
5053
5054   // assign result to variable (if neccessary)
5055   if (result && AOP_TYPE(result) != AOP_CRY) {
5056     //DEBUGpc ("assign result");
5057     size = AOP_SIZE(result);
5058     while (size--) {
5059       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5060     } // while
5061     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5062   } // if (result)
5063
5064   // perform conditional jump
5065   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5066   if (ifx) {
5067     //DEBUGpc ("generate control flow");
5068     rIfx.condition ^= 1;
5069     genSkipc (&rIfx);
5070     ifx->generated = 1;
5071   } // if
5072 }
5073
5074 #elif 1
5075                 /* { */
5076       /* original code */
5077 static void genCmp (operand *left,operand *right,
5078                     operand *result, iCode *ifx, int sign)
5079 {
5080   int size; //, offset = 0 ;
5081   unsigned long lit = 0L,i = 0;
5082   resolvedIfx rFalseIfx;
5083   //  resolvedIfx rTrueIfx;
5084   symbol *truelbl;
5085   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5086 /*
5087   if(ifx) {
5088     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5089     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5090   }
5091 */
5092
5093   FENTRY;
5094   
5095   resolveIfx(&rFalseIfx,ifx);
5096   truelbl  = newiTempLabel(NULL);
5097   size = max(AOP_SIZE(left),AOP_SIZE(right));
5098
5099   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5100
5101 #define _swapp
5102
5103   /* if literal is on the right then swap with left */
5104   if ((AOP_TYPE(right) == AOP_LIT)) {
5105     operand *tmp = right ;
5106     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5107     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5108 #ifdef _swapp
5109
5110     lit = (lit - 1) & mask;
5111     right = left;
5112     left = tmp;
5113     rFalseIfx.condition ^= 1;
5114 #endif
5115
5116   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5117     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5118   }
5119
5120
5121   //if(IC_TRUE(ifx) == NULL)
5122   /* if left & right are bit variables */
5123   if (AOP_TYPE(left) == AOP_CRY &&
5124       AOP_TYPE(right) == AOP_CRY ) {
5125     assert (0 && "bit variables used in genCmp");
5126     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5127     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5128   } else {
5129     /* subtract right from left if at the
5130        end the carry flag is set then we know that
5131        left is greater than right */
5132
5133     symbol *lbl  = newiTempLabel(NULL);
5134
5135 #if 0
5136         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5137                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5138 #endif
5139
5140 #ifndef _swapp
5141     if(AOP_TYPE(right) == AOP_LIT) {
5142
5143       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5144
5145       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5146
5147       /* special cases */
5148
5149       if(lit == 0) {
5150
5151         if(sign != 0) 
5152           genSkipCond(&rFalseIfx,left,size-1,7);
5153         else 
5154           /* no need to compare to 0...*/
5155           /* NOTE: this is a de-generate compare that most certainly 
5156            *       creates some dead code. */
5157           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5158
5159         if(ifx) ifx->generated = 1;
5160         return;
5161
5162       }
5163       size--;
5164
5165       if(size == 0) {
5166         //i = (lit >> (size*8)) & 0xff;
5167         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5168         
5169         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5170
5171         i = ((0-lit) & 0xff);
5172         if(sign) {
5173           if( i == 0x81) { 
5174             /* lit is 0x7f, all signed chars are less than
5175              * this except for 0x7f itself */
5176             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5177             genSkipz2(&rFalseIfx,0);
5178           } else {
5179             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5180             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5181             genSkipc(&rFalseIfx);
5182           }
5183
5184         } else {
5185           if(lit == 1) {
5186             genSkipz2(&rFalseIfx,1);
5187           } else {
5188             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5189             genSkipc(&rFalseIfx);
5190           }
5191         }
5192
5193         if(ifx) ifx->generated = 1;
5194         return;
5195       }
5196
5197       /* chars are out of the way. now do ints and longs */
5198
5199
5200       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5201         
5202       /* special cases */
5203
5204       if(sign) {
5205
5206         if(lit == 0) {
5207           genSkipCond(&rFalseIfx,left,size,7);
5208           if(ifx) ifx->generated = 1;
5209           return;
5210         }
5211
5212         if(lit <0x100) {
5213           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5214
5215           //rFalseIfx.condition ^= 1;
5216           //genSkipCond(&rFalseIfx,left,size,7);
5217           //rFalseIfx.condition ^= 1;
5218
5219           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5220           if(rFalseIfx.condition)
5221             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5222           else
5223             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5224
5225           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5226           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5228
5229           while(size > 1)
5230             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5231
5232           if(rFalseIfx.condition) {
5233             emitSKPZ;
5234             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5235
5236           } else {
5237             emitSKPNZ;
5238           }
5239
5240           genSkipc(&rFalseIfx);
5241           pic16_emitpLabel(truelbl->key);
5242           if(ifx) ifx->generated = 1;
5243           return;
5244
5245         }
5246
5247         if(size == 1) {
5248
5249           if( (lit & 0xff) == 0) {
5250             /* lower byte is zero */
5251             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5252             i = ((lit >> 8) & 0xff) ^0x80;
5253             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5254             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5255             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5256             genSkipc(&rFalseIfx);
5257
5258
5259             if(ifx) ifx->generated = 1;
5260             return;
5261
5262           }
5263         } else {
5264           /* Special cases for signed longs */
5265           if( (lit & 0xffffff) == 0) {
5266             /* lower byte is zero */
5267             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5268             i = ((lit >> 8*3) & 0xff) ^0x80;
5269             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5270             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5271             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5272             genSkipc(&rFalseIfx);
5273
5274
5275             if(ifx) ifx->generated = 1;
5276             return;
5277
5278           }
5279
5280         }
5281
5282
5283         if(lit & (0x80 << (size*8))) {
5284           /* lit is negative */
5285           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5286
5287           //genSkipCond(&rFalseIfx,left,size,7);
5288
5289           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5290
5291           if(rFalseIfx.condition)
5292             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5293           else
5294             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5295
5296
5297         } else {
5298           /* lit is positive */
5299           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5300           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5301           if(rFalseIfx.condition)
5302             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5303           else
5304             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5305
5306         }
5307
5308         /*
5309           This works, but is only good for ints.
5310           It also requires a "known zero" register.
5311           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5312           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5313           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5314           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5315           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5316           genSkipc(&rFalseIfx);
5317
5318           pic16_emitpLabel(truelbl->key);
5319           if(ifx) ifx->generated = 1;
5320           return;
5321         **/
5322           
5323         /* There are no more special cases, so perform a general compare */
5324   
5325         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5326         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5327
5328         while(size--) {
5329
5330           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5331           emitSKPNZ;
5332           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5333         }
5334         //rFalseIfx.condition ^= 1;
5335         genSkipc(&rFalseIfx);
5336
5337         pic16_emitpLabel(truelbl->key);
5338
5339         if(ifx) ifx->generated = 1;
5340         return;
5341
5342
5343       }
5344
5345
5346       /* sign is out of the way. So now do an unsigned compare */
5347       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5348
5349
5350       /* General case - compare to an unsigned literal on the right.*/
5351
5352       i = (lit >> (size*8)) & 0xff;
5353       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5354       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5355       while(size--) {
5356         i = (lit >> (size*8)) & 0xff;
5357
5358         if(i) {
5359           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5360           emitSKPNZ;
5361           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5362         } else {
5363           /* this byte of the lit is zero, 
5364            *if it's not the last then OR in the variable */
5365           if(size)
5366             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5367         }
5368       }
5369
5370
5371       pic16_emitpLabel(lbl->key);
5372 //      pic16_emitpLabel(truelbl->key);
5373       //if(emitFinalCheck)
5374       genSkipc(&rFalseIfx);
5375       if(sign)
5376         pic16_emitpLabel(truelbl->key);
5377
5378       if(ifx) ifx->generated = 1;
5379       return;
5380
5381
5382     }
5383 #endif  // _swapp
5384
5385     if(AOP_TYPE(left) == AOP_LIT) {
5386       //symbol *lbl = newiTempLabel(NULL);
5387
5388       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5389
5390
5391       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5392
5393       /* Special cases */
5394       if((lit == 0) && (sign == 0)){
5395
5396         size--;
5397         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5398         while(size) 
5399           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5400
5401         genSkipz2(&rFalseIfx,0);
5402         if(ifx) ifx->generated = 1;
5403         return;
5404       }
5405
5406       if(size==1) {
5407         /* Special cases */
5408         lit &= 0xff;
5409         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5410           /* degenerate compare can never be true */
5411           if(rFalseIfx.condition == 0)
5412             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5413
5414           if(ifx) ifx->generated = 1;
5415           return;
5416         }
5417
5418         if(sign) {
5419           /* signed comparisons to a literal byte */
5420
5421           int lp1 = (lit+1) & 0xff;
5422
5423           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5424           switch (lp1) {
5425           case 0:
5426             rFalseIfx.condition ^= 1;
5427             genSkipCond(&rFalseIfx,right,0,7);
5428             break;
5429           case 0x7f:
5430             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5431             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5432             genSkipz2(&rFalseIfx,1);
5433             break;
5434           default:
5435             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5436             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5437             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5438             rFalseIfx.condition ^= 1;
5439             genSkipc(&rFalseIfx);
5440             break;
5441           }
5442         } else {
5443           /* unsigned comparisons to a literal byte */
5444
5445           switch(lit & 0xff ) {
5446           case 0:
5447             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5448             genSkipz2(&rFalseIfx,0);
5449             break;
5450           case 0x7f:
5451             rFalseIfx.condition ^= 1;
5452             genSkipCond(&rFalseIfx,right,0,7);
5453             break;
5454
5455           default:
5456             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5457             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5458             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5459             rFalseIfx.condition ^= 1;
5460             if (AOP_TYPE(result) == AOP_CRY)
5461               genSkipc(&rFalseIfx);
5462             else {
5463               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5464               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5465             }         
5466             break;
5467           }
5468         }
5469
5470         if(ifx) ifx->generated = 1;
5471         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5472                 goto check_carry;
5473         return;
5474
5475       } else {
5476
5477         /* Size is greater than 1 */
5478
5479         if(sign) {
5480           int lp1 = lit+1;
5481
5482           size--;
5483
5484           if(lp1 == 0) {
5485             /* this means lit = 0xffffffff, or -1 */
5486
5487
5488             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5489             rFalseIfx.condition ^= 1;
5490             genSkipCond(&rFalseIfx,right,size,7);
5491             if(ifx) ifx->generated = 1;
5492
5493             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5494               goto check_carry;
5495
5496             return;
5497           }
5498
5499           if(lit == 0) {
5500             int s = size;
5501
5502             if(rFalseIfx.condition) {
5503               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5504               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5505             }
5506
5507             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5508             while(size--)
5509               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5510
5511
5512             emitSKPZ;
5513             if(rFalseIfx.condition) {
5514               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5515               pic16_emitpLabel(truelbl->key);
5516             }else {
5517               rFalseIfx.condition ^= 1;
5518               genSkipCond(&rFalseIfx,right,s,7);
5519             }
5520
5521             if(ifx) ifx->generated = 1;
5522
5523             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5524               goto check_carry;
5525
5526             return;
5527           }
5528
5529           if((size == 1) &&  (0 == (lp1&0xff))) {
5530             /* lower byte of signed word is zero */
5531             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5532             i = ((lp1 >> 8) & 0xff) ^0x80;
5533             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5534             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5535             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5536
5537             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5538               emitTOGC;
5539               if(ifx) ifx->generated = 1;
5540               goto check_carry;
5541             } else {
5542               rFalseIfx.condition ^= 1;
5543               genSkipc(&rFalseIfx);
5544               if(ifx) ifx->generated = 1;
5545             }
5546
5547             return;
5548           }
5549
5550           if(lit & (0x80 << (size*8))) {
5551             /* Lit is less than zero */
5552             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5553             //rFalseIfx.condition ^= 1;
5554             //genSkipCond(&rFalseIfx,left,size,7);
5555             //rFalseIfx.condition ^= 1;
5556             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5557             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5558
5559             if(rFalseIfx.condition)
5560               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5561             else
5562               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5563
5564
5565           } else {
5566             /* Lit is greater than or equal to zero */
5567             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5568             //rFalseIfx.condition ^= 1;
5569             //genSkipCond(&rFalseIfx,right,size,7);
5570             //rFalseIfx.condition ^= 1;
5571
5572             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5573             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5574
5575             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5576             if(rFalseIfx.condition)
5577               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5578             else
5579               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5580
5581           }
5582
5583           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5584           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5585
5586           while(size--) {
5587
5588             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5589             emitSKPNZ;
5590             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5591           }
5592           rFalseIfx.condition ^= 1;
5593           //rFalseIfx.condition = 1;
5594           genSkipc(&rFalseIfx);
5595
5596           pic16_emitpLabel(truelbl->key);
5597
5598           if(ifx) ifx->generated = 1;
5599
5600
5601           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5602             goto check_carry;
5603
5604           return;
5605           // end of if (sign)
5606         } else {
5607
5608           /* compare word or long to an unsigned literal on the right.*/
5609
5610
5611           size--;
5612           if(lit < 0xff) {
5613             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5614             switch (lit) {
5615             case 0:
5616               break; /* handled above */
5617 /*
5618             case 0xff:
5619               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5620               while(size--)
5621                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5622               genSkipz2(&rFalseIfx,0);
5623               break;
5624 */
5625             default:
5626               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5627               while(--size)
5628                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5629
5630               emitSKPZ;
5631               if(rFalseIfx.condition)
5632                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5633               else
5634                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5635
5636
5637               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5638               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5639
5640               rFalseIfx.condition ^= 1;
5641               genSkipc(&rFalseIfx);
5642             }
5643
5644             pic16_emitpLabel(truelbl->key);
5645
5646             if(ifx) ifx->generated = 1;
5647
5648             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649               goto check_carry;
5650
5651             return;
5652           }
5653
5654
5655           lit++;
5656           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5657           i = (lit >> (size*8)) & 0xff;
5658
5659           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5660           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5661
5662           while(size--) {
5663             i = (lit >> (size*8)) & 0xff;
5664
5665             if(i) {
5666               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5667               emitSKPNZ;
5668               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5669             } else {
5670               /* this byte of the lit is zero, 
5671                * if it's not the last then OR in the variable */
5672               if(size)
5673                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5674             }
5675           }
5676
5677
5678           pic16_emitpLabel(lbl->key);
5679
5680           rFalseIfx.condition ^= 1;
5681
5682           genSkipc(&rFalseIfx);
5683         }
5684
5685         if(sign)
5686           pic16_emitpLabel(truelbl->key);
5687         if(ifx) ifx->generated = 1;
5688
5689             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5690               goto check_carry;
5691
5692         return;
5693       }
5694     }
5695     /* Compare two variables */
5696
5697     DEBUGpic16_emitcode(";sign","%d",sign);
5698
5699     size--;
5700     if(sign) {
5701       /* Sigh. thus sucks... */
5702       if(size) {
5703         pCodeOp *pctemp;
5704         
5705         pctemp = pic16_popGetTempReg(1);
5706         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5707         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5708         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5709         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5710         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5711         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5712         pic16_popReleaseTempReg(pctemp, 1);
5713       } else {
5714         /* Signed char comparison */
5715         /* Special thanks to Nikolai Golovchenko for this snippet */
5716         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5717         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5718         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5719         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5720         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5721         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5722
5723         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5724         genSkipc(&rFalseIfx);
5725           
5726         if(ifx) ifx->generated = 1;
5727
5728             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5729               goto check_carry;
5730
5731         return;
5732       }
5733
5734     } else {
5735
5736       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5738     }
5739
5740
5741     /* The rest of the bytes of a multi-byte compare */
5742     while (size) {
5743
5744       emitSKPZ;
5745       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5746       size--;
5747
5748       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5749       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5750
5751
5752     }
5753
5754     pic16_emitpLabel(lbl->key);
5755
5756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5757     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5758         (AOP_TYPE(result) == AOP_REG)) {
5759       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5760       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5761     } else {
5762       genSkipc(&rFalseIfx);
5763     }         
5764     //genSkipc(&rFalseIfx);
5765     if(ifx) ifx->generated = 1;
5766
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771     return;
5772
5773   }
5774
5775 check_carry:
5776   if ((AOP_TYPE(result) != AOP_CRY) 
5777         && AOP_SIZE(result)) {
5778     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5779
5780     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5781
5782     pic16_outBitC(result);
5783   } else {
5784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5785     /* if the result is used in the next
5786        ifx conditional branch then generate
5787        code a little differently */
5788     if (ifx )
5789       genIfxJump (ifx,"c");
5790     else
5791       pic16_outBitC(result);
5792     /* leave the result in acc */
5793   }
5794
5795 }
5796
5797 #else   /* old version of genCmp() */   /* } else { */
5798
5799 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5800 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5801         operand *result, int offset, int invert_op)
5802 {
5803   /* add code here */
5804   
5805   /* check condition, > or < ?? */
5806   if(rIfx->condition != 0)invert_op ^= 1;
5807   
5808   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5809
5810   if(!ifx)invert_op ^= 1;
5811
5812   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5813       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5814   
5815   /* do selection */
5816   if(!invert_op)return POC_CPFSGT;
5817   else return POC_CPFSLT;
5818 }
5819
5820 static int compareAopfirstpass=1;
5821
5822 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5823             operand *oper, int offset, operand *result,
5824             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5825             symbol *tlbl)
5826 {
5827   int op;
5828   symbol *truelbl;
5829
5830   /* invert if there is a result to be loaded, in order to fit,
5831    * SETC/CLRC sequence */
5832   if(AOP_SIZE(result))invert_op ^= 1;
5833
5834 //  if(sign && !offset)invert_op ^= 1;
5835   
5836 //  if(sign)invert_op ^= 1;
5837   
5838   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5839
5840   if(AOP_SIZE(result) && compareAopfirstpass) {
5841     if(!ifx) {
5842       if(pcop2)
5843         pic16_emitpcode(POC_SETF, pcop2);
5844       else
5845         emitSETC;
5846     } else {
5847       if(pcop2)
5848         pic16_emitpcode(POC_CLRF, pcop2);
5849       else
5850         emitCLRC;
5851     }
5852   }
5853
5854   compareAopfirstpass = 0;
5855
5856       /* there is a bug when comparing operands with size > 1,
5857        * because higher bytes can be equal and test should be performed
5858        * to the next lower byte, current algorithm, considers operands
5859        * inequal in these cases! -- VR 20041107 */
5860
5861     
5862   if(pcop)
5863     pic16_emitpcode(op, pcop);
5864   else
5865     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5866
5867
5868   if((!sign || !offset) && AOP_SIZE(result)) {
5869     if(!ifx) {
5870       if(pcop2)
5871         pic16_emitpcode(POC_CLRF, pcop2);
5872         else
5873         emitCLRC;
5874     } else {
5875       if(pcop2)
5876         pic16_emitpcode(POC_SETF, pcop2);
5877       else
5878         emitSETC;
5879     }
5880     
5881     /* don't emit final branch (offset == 0) */
5882     if(offset) {
5883
5884       if(pcop2)
5885         pic16_emitpcode(POC_RRCF, pcop2);
5886
5887       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5888     }
5889   } else {
5890     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5891       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5892             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5893
5894       truelbl = newiTempLabel( NULL );
5895       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5896       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5897         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5898       else
5899         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5900       pic16_emitpLabel(truelbl->key);
5901     } else {
5902       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5903     }
5904   }
5905 }
5906
5907
5908   
5909
5910 #if 1   /* { */
5911 static void genCmp (operand *left, operand *right,
5912                     operand *result, iCode *ifx, int sign)
5913 {
5914   int size, cmpop=1;
5915   long lit = 0L;
5916   resolvedIfx rFalseIfx;
5917   symbol *falselbl, *tlbl;
5918
5919     FENTRY;
5920     
5921     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5922
5923     resolveIfx(&rFalseIfx, ifx);
5924     size = max(AOP_SIZE(left), AOP_SIZE(right));
5925     
5926     /* if left & right are bit variables */
5927     if(AOP_TYPE(left) == AOP_CRY
5928       && AOP_TYPE(right) == AOP_CRY ) {
5929
5930         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5931         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5932         
5933         werror(W_POSSBUG2, __FILE__, __LINE__);
5934         exit(-1);
5935     }
5936     
5937     /* if literal is on the right then swap with left */
5938     if((AOP_TYPE(right) == AOP_LIT)) {
5939       operand *tmp = right ;
5940 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5941
5942         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5943
5944 //      lit = (lit - 1) & mask;
5945         right = left;
5946         left = tmp;
5947         rFalseIfx.condition ^= 1;               /* reverse compare */
5948     } else
5949     if ((AOP_TYPE(left) == AOP_LIT)) {
5950       /* float compares are handled by support functions */
5951       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5952     }
5953
5954     /* actual comparing algorithm */
5955 //    size = AOP_SIZE( right );
5956
5957     falselbl = newiTempLabel( NULL );
5958     if(AOP_TYPE(left) == AOP_LIT) {
5959       /* compare to literal */
5960       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5961       
5962       if(sign) {
5963         pCodeOp *pct, *pct2;
5964         symbol *tlbl1;
5965
5966         /* signed compare */
5967         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5968
5969         pct = pic16_popCopyReg(&pic16_pc_prodl);
5970         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5971         tlbl = newiTempLabel( NULL );
5972         
5973         /* first compare signs:
5974          *  a. if both are positive, compare just like unsigned
5975          *  b. if both are negative, invert cmpop, compare just like unsigned
5976          *  c. if different signs, determine the result directly */
5977
5978         size--;
5979
5980 #if 1
5981         /* { */
5982         tlbl1 = newiTempLabel( NULL );
5983 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5984
5985         if(lit > 0) {
5986
5987           /* literal is zero or positive:
5988            *  a. if carry is zero, too, continue compare,
5989            *  b. if carry is set, then continue depending on cmpop ^ condition:
5990            *    1. '<' return false (literal < variable),
5991            *    2. '>' return true (literal > variable) */
5992 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5993           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5994           
5995           
5996           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5997           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5998         } else 
5999         if(lit < 0) {
6000           
6001           /* literal is negative:
6002            *  a. if carry is set, too, continue compare,
6003            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6004            *    1. '<' return true (literal < variable),
6005            *    2. '>' return false (literal > variable) */
6006 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6007           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6008           
6009           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6010           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6011         }
6012 #if 1
6013         else {
6014           /* lit == 0 */
6015           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6016           
6017           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6018           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6019         }
6020 #endif
6021         
6022         
6023         pic16_emitpLabel( tlbl1->key );
6024 #endif  /* } */
6025
6026         compareAopfirstpass=1;
6027 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6028 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6029 //        pic16_emitpcode(POC_MOVWF, pct);
6030
6031 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6032         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6033 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6034         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6035
6036         /* generic case */        
6037           while( size-- ) {
6038 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6039 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6040 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6041 //            pic16_emitpcode(POC_MOVWF, pct);
6042
6043 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6044             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6045             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6046 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6047 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6048           }
6049 //        }
6050         
6051         if(ifx)ifx->generated = 1;
6052
6053         if(AOP_SIZE(result)) {
6054           pic16_emitpLabel(tlbl->key);
6055           pic16_emitpLabel(falselbl->key);
6056           pic16_outBitOp( result, pct2 );
6057         } else {
6058           pic16_emitpLabel(tlbl->key);
6059         }
6060       } else {
6061
6062
6063         /* unsigned compare */      
6064         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6065     
6066         compareAopfirstpass=1;
6067         while(size--) {
6068           
6069           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6070           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6071
6072         }
6073
6074         if(ifx)ifx->generated = 1;
6075
6076
6077         if(AOP_SIZE(result)) {
6078           pic16_emitpLabel(falselbl->key);
6079           pic16_outBitC( result );
6080         }
6081
6082       }
6083     } else {
6084       /* compare registers */
6085       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6086
6087
6088       if(sign) {
6089         pCodeOp *pct, *pct2;
6090         
6091         /* signed compare */
6092         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6093
6094         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6095         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6096         tlbl = newiTempLabel( NULL );
6097         
6098         compareAopfirstpass=1;
6099
6100         size--;
6101         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6102 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6103         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6104         pic16_emitpcode(POC_MOVWF, pct);
6105
6106         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6107 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6108         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6109
6110         /* WREG already holds left + 0x80 */
6111         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6112         
6113         while( size-- ) {
6114           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6115 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6116           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6117           pic16_emitpcode(POC_MOVWF, pct);
6118                 
6119           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6120 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6121           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6122
6123           /* WREG already holds left + 0x80 */
6124           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6125 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6126         }
6127         
6128         if(ifx)ifx->generated = 1;
6129
6130         if(AOP_SIZE(result)) {
6131           pic16_emitpLabel(tlbl->key);
6132           pic16_emitpLabel(falselbl->key);
6133           pic16_outBitOp( result, pct2 );
6134         } else {
6135           pic16_emitpLabel(tlbl->key);
6136         }
6137
6138       } else {
6139         /* unsigned compare */      
6140         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6141
6142         compareAopfirstpass=1;
6143         while(size--) {
6144           
6145           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6146           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6147
6148         }
6149
6150         if(ifx)ifx->generated = 1;
6151         if(AOP_SIZE(result)) {
6152
6153           pic16_emitpLabel(falselbl->key);
6154           pic16_outBitC( result );
6155         }
6156
6157       }
6158     }
6159 }
6160
6161 #else    /* } else { */
6162
6163 /* new version of genCmp -- VR 20041012 */
6164 static void genCmp (operand *left,operand *right,
6165                     operand *result, iCode *ifx, int sign)
6166 {
6167   int size; //, offset = 0 ;
6168   unsigned long lit = 0L,i = 0;
6169   resolvedIfx rFalseIfx;
6170   int willCheckCarry=0;
6171   //  resolvedIfx rTrueIfx;
6172   symbol *truelbl;
6173
6174     FENTRY;
6175   
6176   /* General concept:
6177    * subtract right from left if at the end the carry flag is set then we
6178    * know that left is greater than right */
6179             
6180   resolveIfx(&rFalseIfx,ifx);
6181   truelbl  = newiTempLabel(NULL);
6182   size = max(AOP_SIZE(left),AOP_SIZE(right));
6183
6184   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6185
6186   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6187    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6188   
6189
6190   /* if literal is on the right then swap with left */
6191   if ((AOP_TYPE(right) == AOP_LIT)) {
6192     operand *tmp = right ;
6193     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6194
6195       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6196
6197 //      lit = (lit - 1) & mask;
6198       right = left;
6199       left = tmp;
6200       rFalseIfx.condition ^= 1;         /* reverse compare */
6201   } else
6202   if ((AOP_TYPE(left) == AOP_LIT)) {
6203     /* float compares are handled by support functions */
6204     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6205   }
6206
6207
6208   //if(IC_TRUE(ifx) == NULL)
6209   /* if left & right are bit variables */
6210   if (AOP_TYPE(left) == AOP_CRY &&
6211       AOP_TYPE(right) == AOP_CRY ) {
6212
6213     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6214     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6215
6216   } else {
6217     symbol *lbl  = newiTempLabel(NULL);
6218
6219     if(AOP_TYPE(left) == AOP_LIT) {
6220       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6221
6222       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6223         willCheckCarry = 1;
6224       else willCheckCarry = 0;
6225
6226       /* Special cases */
6227       if((lit == 0) && (sign == 0)) {
6228         /* unsigned compare to 0 */
6229         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6230         
6231         size--;
6232         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6233         while(size) 
6234           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6235
6236         genSkipz2(&rFalseIfx,0);
6237         if(ifx)ifx->generated = 1;
6238         return;
6239       }
6240
6241       if(size==1) {
6242         /* Special cases */
6243         lit &= 0xff;
6244         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6245           /* degenerate compare can never be true */
6246           if(rFalseIfx.condition == 0)
6247             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6248
6249           if(ifx) ifx->generated = 1;
6250           return;
6251         }
6252
6253         if(sign) {
6254           /* signed comparisons to a literal byte */
6255           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6256
6257           int lp1 = (lit+1) & 0xff;
6258
6259           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6260           switch (lp1) {
6261           case 0:
6262             rFalseIfx.condition ^= 1;
6263             genSkipCond(&rFalseIfx,right,0,7);
6264             break;
6265           case 0x7f:
6266             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6267             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6268             genSkipz2(&rFalseIfx,1);
6269             break;
6270           default:
6271             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6272             
6273             if(rFalseIfx.condition)
6274               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6275             else
6276               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6277
6278             if(willCheckCarry) {
6279               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6280               else { emitSETC; emitCLRC; }
6281               
6282             } else {
6283               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6284             }              
6285                       
6286 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6287             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6288             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6289             rFalseIfx.condition ^= 1;
6290             genSkipc(&rFalseIfx);
6291 */
6292             break;
6293           }
6294         } else {
6295           /* unsigned comparisons to a literal byte */
6296           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6297
6298           switch(lit & 0xff ) {
6299                           /* special cases */
6300           case 0:
6301             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6302             genSkipz2(&rFalseIfx,0);
6303             break;
6304           case 0x7f:
6305             rFalseIfx.condition ^= 1;
6306             genSkipCond(&rFalseIfx,right,0,7);
6307             break;
6308           default:
6309             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6310             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6311             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6312             rFalseIfx.condition ^= 1;
6313             if (AOP_TYPE(result) == AOP_CRY)
6314               genSkipc(&rFalseIfx);
6315             else {
6316               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6317               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6318             }         
6319             break;
6320           }
6321         }
6322
6323         if(ifx) ifx->generated = 1;
6324         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6325                 goto check_carry;
6326         return;
6327
6328       } else {
6329
6330         /* Size is greater than 1 */
6331
6332         if(sign) {
6333           int lp1 = lit+1;
6334
6335           size--;
6336
6337           if(lp1 == 0) {
6338             /* this means lit = 0xffffffff, or -1 */
6339
6340
6341             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6342             rFalseIfx.condition ^= 1;
6343             genSkipCond(&rFalseIfx,right,size,7);
6344             if(ifx) ifx->generated = 1;
6345             return;
6346           }
6347
6348           if(lit == 0) {
6349             int s = size;
6350
6351             if(rFalseIfx.condition) {
6352               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6353               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6354             }
6355
6356             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6357             while(size--)
6358               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6359
6360
6361             emitSKPZ;
6362             if(rFalseIfx.condition) {
6363               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6364               pic16_emitpLabel(truelbl->key);
6365             }else {
6366               rFalseIfx.condition ^= 1;
6367               genSkipCond(&rFalseIfx,right,s,7);
6368             }
6369
6370             if(ifx) ifx->generated = 1;
6371             return;
6372           }
6373
6374           if((size == 1) &&  (0 == (lp1&0xff))) {
6375             /* lower byte of signed word is zero */
6376             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6377             i = ((lp1 >> 8) & 0xff) ^0x80;
6378             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6379             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6380             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6381             rFalseIfx.condition ^= 1;
6382             genSkipc(&rFalseIfx);
6383
6384
6385             if(ifx) ifx->generated = 1;
6386             return;
6387           }
6388
6389           if(lit & (0x80 << (size*8))) {
6390             /* Lit is less than zero */
6391             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6392             //rFalseIfx.condition ^= 1;
6393             //genSkipCond(&rFalseIfx,left,size,7);
6394             //rFalseIfx.condition ^= 1;
6395             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6396             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6397
6398             if(rFalseIfx.condition)
6399               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6400             else
6401               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6402
6403
6404           } else {
6405             /* Lit is greater than or equal to zero */
6406             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6407             //rFalseIfx.condition ^= 1;
6408             //genSkipCond(&rFalseIfx,right,size,7);
6409             //rFalseIfx.condition ^= 1;
6410
6411             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6412             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6413
6414             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6415             if(rFalseIfx.condition)
6416               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6417             else
6418               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6419
6420           }
6421
6422
6423           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6424           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6425
6426           while(size--) {
6427
6428             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6429             emitSKPNZ;
6430             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6431           }
6432           rFalseIfx.condition ^= 1;
6433           //rFalseIfx.condition = 1;
6434           genSkipc(&rFalseIfx);
6435
6436           pic16_emitpLabel(truelbl->key);
6437
6438           if(ifx) ifx->generated = 1;
6439           return;
6440           // end of if (sign)
6441         } else {
6442
6443           /* compare word or long to an unsigned literal on the right.*/
6444
6445
6446           size--;
6447           if(lit < 0xff) {
6448             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6449             switch (lit) {
6450             case 0:
6451               break; /* handled above */
6452 /*
6453             case 0xff:
6454               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6455               while(size--)
6456                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6457               genSkipz2(&rFalseIfx,0);
6458               break;
6459 */
6460             default:
6461               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6462               while(--size)
6463                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6464
6465               emitSKPZ;
6466               if(rFalseIfx.condition)
6467                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6468               else
6469                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6470
6471
6472               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6473               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6474
6475               rFalseIfx.condition ^= 1;
6476               genSkipc(&rFalseIfx);
6477             }
6478
6479             pic16_emitpLabel(truelbl->key);
6480
6481             if(ifx) ifx->generated = 1;
6482             return;
6483           }
6484
6485
6486           lit++;
6487           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6488           i = (lit >> (size*8)) & 0xff;
6489
6490           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6491           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6492
6493           while(size--) {
6494             i = (lit >> (size*8)) & 0xff;
6495
6496             if(i) {
6497               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6498               emitSKPNZ;
6499               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6500             } else {
6501               /* this byte of the lit is zero, 
6502                * if it's not the last then OR in the variable */
6503               if(size)
6504                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6505             }
6506           }
6507
6508
6509           pic16_emitpLabel(lbl->key);
6510
6511           rFalseIfx.condition ^= 1;
6512
6513           genSkipc(&rFalseIfx);
6514         }
6515
6516         if(sign)
6517           pic16_emitpLabel(truelbl->key);
6518         if(ifx) ifx->generated = 1;
6519         return;
6520       }
6521     }
6522     /* Compare two variables */
6523
6524     DEBUGpic16_emitcode(";sign","%d",sign);
6525
6526     size--;
6527     if(sign) {
6528       /* Sigh. thus sucks... */
6529       if(size) {
6530         pCodeOp *pctemp;
6531         
6532         pctemp = pic16_popGetTempReg(1);
6533         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6534         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6535         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6536         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6537         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6538         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6539         pic16_popReleaseTempReg(pctemp, 1);
6540       } else {
6541         /* Signed char comparison */
6542         /* Special thanks to Nikolai Golovchenko for this snippet */
6543         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6544         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6545         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6546         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6547         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6548         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6549
6550         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6551         genSkipc(&rFalseIfx);
6552           
6553         if(ifx) ifx->generated = 1;
6554         return;
6555       }
6556
6557     } else {
6558
6559       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6560       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6561     }
6562
6563
6564     /* The rest of the bytes of a multi-byte compare */
6565     while (size) {
6566
6567       emitSKPZ;
6568       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6569       size--;
6570
6571       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6572       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6573
6574
6575     }
6576
6577     pic16_emitpLabel(lbl->key);
6578
6579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6580     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6581         (AOP_TYPE(result) == AOP_REG)) {
6582       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6583       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6584     } else {
6585       genSkipc(&rFalseIfx);
6586     }         
6587     //genSkipc(&rFalseIfx);
6588     if(ifx) ifx->generated = 1;
6589
6590     return;
6591
6592   }
6593
6594 check_carry:
6595   if ((AOP_TYPE(result) != AOP_CRY) 
6596         && AOP_SIZE(result)) {
6597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6598
6599     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6600
6601     pic16_outBitC(result);
6602   } else {
6603     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6604     /* if the result is used in the next
6605        ifx conditional branch then generate
6606        code a little differently */
6607     if (ifx )
6608       genIfxJump (ifx,"c");
6609     else
6610       pic16_outBitC(result);
6611     /* leave the result in acc */
6612   }
6613
6614 }
6615 #endif  /* } */
6616
6617
6618 #endif  /* } */
6619
6620
6621
6622 /*-----------------------------------------------------------------*/
6623 /* genCmpGt :- greater than comparison                             */
6624 /*-----------------------------------------------------------------*/
6625 static void genCmpGt (iCode *ic, iCode *ifx)
6626 {
6627   operand *left, *right, *result;
6628   sym_link *letype , *retype;
6629   int sign ;
6630
6631     FENTRY;
6632     
6633     left = IC_LEFT(ic);
6634     right= IC_RIGHT(ic);
6635     result = IC_RESULT(ic);
6636
6637     letype = getSpec(operandType(left));
6638     retype =getSpec(operandType(right));
6639     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6640     /* assign the amsops */
6641     pic16_aopOp (left,ic,FALSE);
6642     pic16_aopOp (right,ic,FALSE);
6643     pic16_aopOp (result,ic,TRUE);
6644
6645     genCmp(right, left, result, ifx, sign);
6646
6647     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6648     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6649     pic16_freeAsmop(result,NULL,ic,TRUE); 
6650 }
6651
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpLt - less than comparisons                                */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpLt (iCode *ic, iCode *ifx)
6656 {
6657   operand *left, *right, *result;
6658   sym_link *letype , *retype;
6659   int sign ;
6660
6661     FENTRY;
6662
6663     left = IC_LEFT(ic);
6664     right= IC_RIGHT(ic);
6665     result = IC_RESULT(ic);
6666
6667     letype = getSpec(operandType(left));
6668     retype =getSpec(operandType(right));
6669     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6670
6671     /* assign the amsops */
6672     pic16_aopOp (left,ic,FALSE);
6673     pic16_aopOp (right,ic,FALSE);
6674     pic16_aopOp (result,ic,TRUE);
6675
6676     genCmp(left, right, result, ifx, sign);
6677
6678     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6679     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6680     pic16_freeAsmop(result,NULL,ic,TRUE); 
6681 }
6682
6683 #if 0
6684 // not needed ATM
6685 // FIXME reenable literal optimisation when the pic16 port is stable
6686
6687 /*-----------------------------------------------------------------*/
6688 /* genc16bit2lit - compare a 16 bit value to a literal             */
6689 /*-----------------------------------------------------------------*/
6690 static void genc16bit2lit(operand *op, int lit, int offset)
6691 {
6692   int i;
6693
6694   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6695   if( (lit&0xff) == 0) 
6696     i=1;
6697   else
6698     i=0;
6699
6700   switch( BYTEofLONG(lit,i)) { 
6701   case 0:
6702     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6703     break;
6704   case 1:
6705     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6706     break;
6707   case 0xff:
6708     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6709     break;
6710   default:
6711     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6712     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6713   }
6714
6715   i ^= 1;
6716
6717   switch( BYTEofLONG(lit,i)) { 
6718   case 0:
6719     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6720     break;
6721   case 1:
6722     emitSKPNZ;
6723     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6724     break;
6725   case 0xff:
6726     emitSKPNZ;
6727     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6728     break;
6729   default:
6730     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6731     emitSKPNZ;
6732     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6733
6734   }
6735
6736 }
6737 #endif
6738
6739 #if 0
6740 // not needed ATM
6741 /*-----------------------------------------------------------------*/
6742 /* gencjneshort - compare and jump if not equal                    */
6743 /*-----------------------------------------------------------------*/
6744 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6745 {
6746   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6747   int offset = 0;
6748   int res_offset = 0;  /* the result may be a different size then left or right */
6749   int res_size = AOP_SIZE(result);
6750   resolvedIfx rIfx;
6751   symbol *lbl, *lbl_done;
6752
6753   unsigned long lit = 0L;
6754   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6755
6756   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6757   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6758   if(result)
6759     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6760   resolveIfx(&rIfx,ifx);
6761   lbl =  newiTempLabel(NULL);
6762   lbl_done =  newiTempLabel(NULL);
6763
6764
6765   /* if the left side is a literal or 
6766      if the right is in a pointer register and left 
6767      is not */
6768   if ((AOP_TYPE(left) == AOP_LIT) || 
6769       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6770     operand *t = right;
6771     right = left;
6772     left = t;
6773   }
6774   if(AOP_TYPE(right) == AOP_LIT)
6775     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6776
6777   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6778     preserve_result = 1;
6779
6780   if(result && !preserve_result)
6781     {
6782       int i;
6783       for(i = 0; i < AOP_SIZE(result); i++)
6784         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6785     }
6786
6787
6788   /* if the right side is a literal then anything goes */
6789   if (AOP_TYPE(right) == AOP_LIT &&
6790       AOP_TYPE(left) != AOP_DIR ) {
6791     switch(size) {
6792     case 2:
6793       genc16bit2lit(left, lit, 0);
6794       emitSKPZ;
6795       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6796       break;
6797     default:
6798       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6799       while (size--) {
6800         if(lit & 0xff) {
6801           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6802           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6803         } else {
6804           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6805         }
6806
6807         emitSKPZ;
6808         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6809         offset++;
6810         if(res_offset < res_size-1)
6811           res_offset++;
6812         lit >>= 8;
6813       }
6814       break;
6815     }
6816   }
6817
6818   /* if the right side is in a register or in direct space or
6819      if the left is a pointer register & right is not */    
6820   else if (AOP_TYPE(right) == AOP_REG ||
6821            AOP_TYPE(right) == AOP_DIR || 
6822            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6823            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6824     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6825     int lbl_key = lbl->key;
6826
6827     if(result) {
6828       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6829       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6830     }else {
6831       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6832       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6833               __FUNCTION__,__LINE__);
6834       return;
6835     }
6836    
6837 /*     switch(size) { */
6838 /*     case 2: */
6839 /*       genc16bit2lit(left, lit, 0); */
6840 /*       emitSKPNZ; */
6841 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6842 /*       break; */
6843 /*     default: */
6844     while (size--) {
6845       int emit_skip=1;
6846       if((AOP_TYPE(left) == AOP_DIR) && 
6847          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6848
6849         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6850         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6851
6852       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6853             
6854         switch (lit & 0xff) {
6855         case 0:
6856           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6857           break;
6858         case 1:
6859           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6860           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6861           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6862           emit_skip=0;
6863           break;
6864         case 0xff:
6865           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6866           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6867           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6868           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6869           emit_skip=0;
6870           break;
6871         default:
6872           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6873           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6874         }
6875         lit >>= 8;
6876
6877       } else {
6878         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6879       }
6880       if(emit_skip) {
6881         if(AOP_TYPE(result) == AOP_CRY) {
6882           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6883           if(rIfx.condition)
6884             emitSKPNZ;
6885           else
6886             emitSKPZ;
6887           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6888         } else {
6889           /* fix me. probably need to check result size too */
6890           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6891           if(rIfx.condition)
6892             emitSKPZ;
6893           else
6894             emitSKPNZ;
6895           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6896           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6897         }
6898         if(ifx)
6899           ifx->generated=1;
6900       }
6901       emit_skip++;
6902       offset++;
6903       if(res_offset < res_size-1)
6904         res_offset++;
6905     }
6906 /*       break; */
6907 /*     } */
6908   } else if(AOP_TYPE(right) == AOP_REG &&
6909             AOP_TYPE(left) != AOP_DIR){
6910
6911     while(size--) {
6912       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6913       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6914       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6915       if(rIfx.condition)
6916         emitSKPNZ;
6917       else
6918         emitSKPZ;
6919       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6920       offset++;
6921       if(res_offset < res_size-1)
6922         res_offset++;
6923     }
6924       
6925   }else{
6926     /* right is a pointer reg need both a & b */
6927     while(size--) {
6928       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6929       if(strcmp(l,"b"))
6930         pic16_emitcode("mov","b,%s",l);
6931       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6932       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6933       offset++;
6934     }
6935   }
6936
6937   if(result && preserve_result)
6938     {
6939       int i;
6940       for(i = 0; i < AOP_SIZE(result); i++)
6941         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6942     }
6943
6944   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6945
6946   if(result && preserve_result)
6947     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6948
6949   if(!rIfx.condition)
6950     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6951
6952   pic16_emitpLabel(lbl->key);
6953
6954   if(result && preserve_result)
6955     {
6956       int i;
6957       for(i = 0; i < AOP_SIZE(result); i++)
6958         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6959
6960       pic16_emitpLabel(lbl_done->key);
6961    }
6962
6963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6964
6965   if(ifx)
6966     ifx->generated = 1;
6967 }
6968 #endif
6969
6970 #if 0
6971 /*-----------------------------------------------------------------*/
6972 /* gencjne - compare and jump if not equal                         */
6973 /*-----------------------------------------------------------------*/
6974 static void gencjne(operand *left, operand *right, iCode *ifx)
6975 {
6976     symbol *tlbl  = newiTempLabel(NULL);
6977
6978     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6979     gencjneshort(left, right, lbl);
6980
6981     pic16_emitcode("mov","a,%s",one);
6982     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6983     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6984     pic16_emitcode("clr","a");
6985     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6986
6987     pic16_emitpLabel(lbl->key);
6988     pic16_emitpLabel(tlbl->key);
6989
6990 }
6991 #endif
6992
6993
6994 /*-----------------------------------------------------------------*/
6995 /* is_LitOp - check if operand has to be treated as literal        */
6996 /*-----------------------------------------------------------------*/
6997 static bool is_LitOp(operand *op)
6998 {
6999   return ((AOP_TYPE(op) == AOP_LIT)
7000       || ( (AOP_TYPE(op) == AOP_PCODE)
7001           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7002               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7003 }
7004
7005 /*-----------------------------------------------------------------*/
7006 /* is_LitAOp - check if operand has to be treated as literal        */
7007 /*-----------------------------------------------------------------*/
7008 static bool is_LitAOp(asmop *aop)
7009 {
7010   return ((aop->type == AOP_LIT)
7011       || ( (aop->type == AOP_PCODE)
7012           && ( (aop->aopu.pcop->type == PO_LITERAL)
7013               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7014 }
7015
7016
7017
7018 /*-----------------------------------------------------------------*/
7019 /* genCmpEq - generates code for equal to                          */
7020 /*-----------------------------------------------------------------*/
7021 static void genCmpEq (iCode *ic, iCode *ifx)
7022 {
7023   operand *left, *right, *result;
7024   symbol *falselbl = newiTempLabel(NULL);
7025   symbol *donelbl = newiTempLabel(NULL);
7026
7027   int preserve_result = 0;
7028   int generate_result = 0;
7029   int i=0;
7030
7031   FENTRY;
7032   
7033   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7034   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7035   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7036  
7037   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7038
7039   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7040     {
7041       werror(W_POSSBUG2, __FILE__, __LINE__);
7042       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7043       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7044       goto release;
7045     }
7046
7047   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7048     {
7049       operand *tmp = right ;
7050       right = left;
7051       left = tmp;
7052     }
7053
7054   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7055     preserve_result = 1;
7056
7057   if(result && AOP_SIZE(result))
7058     generate_result = 1;
7059
7060   if(generate_result && !preserve_result)
7061     {
7062       for(i = 0; i < AOP_SIZE(result); i++)
7063         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7064     }
7065
7066   for(i=0; i < AOP_SIZE(left); i++)
7067     {
7068       if(AOP_TYPE(left) != AOP_ACC)
7069         {
7070           if(is_LitOp(left))
7071             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7072           else
7073             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7074         }
7075       if(is_LitOp(right))
7076         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7077       else
7078         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7079
7080       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7081     }
7082
7083   // result == true
7084
7085   if(generate_result && preserve_result)
7086     {
7087       for(i = 0; i < AOP_SIZE(result); i++)
7088         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7089     }
7090
7091   if(generate_result)
7092     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7093
7094   if(generate_result && preserve_result)
7095     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7096
7097   if(ifx && IC_TRUE(ifx))
7098     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7099
7100   if(ifx && IC_FALSE(ifx))
7101     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7102
7103   pic16_emitpLabel(falselbl->key);
7104
7105   // result == false
7106
7107   if(ifx && IC_FALSE(ifx))
7108     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7109
7110   if(generate_result && preserve_result)
7111     {
7112       for(i = 0; i < AOP_SIZE(result); i++)
7113         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7114     }
7115
7116   pic16_emitpLabel(donelbl->key);
7117
7118   if(ifx)
7119     ifx->generated = 1;
7120
7121 release:
7122   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7123   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7124   pic16_freeAsmop(result,NULL,ic,TRUE);
7125
7126 }
7127
7128
7129 #if 0
7130 // old version kept for reference
7131
7132 /*-----------------------------------------------------------------*/
7133 /* genCmpEq - generates code for equal to                          */
7134 /*-----------------------------------------------------------------*/
7135 static void genCmpEq (iCode *ic, iCode *ifx)
7136 {
7137     operand *left, *right, *result;
7138     unsigned long lit = 0L;
7139     int size,offset=0;
7140     symbol *falselbl  = newiTempLabel(NULL);
7141
7142
7143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7144
7145     if(ifx)
7146       DEBUGpic16_emitcode ("; ifx is non-null","");
7147     else
7148       DEBUGpic16_emitcode ("; ifx is null","");
7149
7150     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7151     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7152     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7153
7154     size = max(AOP_SIZE(left),AOP_SIZE(right));
7155
7156     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7157
7158     /* if literal, literal on the right or 
7159     if the right is in a pointer register and left 
7160     is not */
7161     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7162         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7163       operand *tmp = right ;
7164       right = left;
7165       left = tmp;
7166     }
7167
7168
7169     if(ifx && !AOP_SIZE(result)){
7170         symbol *tlbl;
7171         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7172         /* if they are both bit variables */
7173         if (AOP_TYPE(left) == AOP_CRY &&
7174             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7175                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7176             if(AOP_TYPE(right) == AOP_LIT){
7177                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7178                 if(lit == 0L){
7179                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7180                     pic16_emitcode("cpl","c");
7181                 } else if(lit == 1L) {
7182                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7183                 } else {
7184                     pic16_emitcode("clr","c");
7185                 }
7186                 /* AOP_TYPE(right) == AOP_CRY */
7187             } else {
7188                 symbol *lbl = newiTempLabel(NULL);
7189                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7190                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7191                 pic16_emitcode("cpl","c");
7192                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7193             }
7194             /* if true label then we jump if condition
7195             supplied is true */
7196             tlbl = newiTempLabel(NULL);
7197             if ( IC_TRUE(ifx) ) {
7198                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7199                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7200             } else {
7201                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7202                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7203             }
7204             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7205
7206                 {
7207                 /* left and right are both bit variables, result is carry */
7208                         resolvedIfx rIfx;
7209               
7210                         resolveIfx(&rIfx,ifx);
7211
7212                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7213                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7214                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7215                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7216                         genSkipz2(&rIfx,0);
7217                 }
7218         } else {
7219
7220                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7221
7222                         /* They're not both bit variables. Is the right a literal? */
7223                         if(AOP_TYPE(right) == AOP_LIT) {
7224                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7225             
7226                         switch(size) {
7227
7228                                 case 1:
7229                                         switch(lit & 0xff) {
7230                                                 case 1:
7231                                                                 if ( IC_TRUE(ifx) ) {
7232                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7233                                                                         emitSKPNZ;
7234                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7235                                                                 } else {
7236                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7237                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7238                                                                 }
7239                                                                 break;
7240                                                 case 0xff:
7241                                                                 if ( IC_TRUE(ifx) ) {
7242                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7243                                                                         emitSKPNZ;
7244                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7245                                                                 } else {
7246                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7247                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7248                                                                 }
7249                                                                 break;
7250                                                 default:
7251                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7252                                                                 if(lit)
7253                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7254                                                                 genSkip(ifx,'z');
7255                                         } // switch lit
7256
7257
7258                                         /* end of size == 1 */
7259                                         break;
7260               
7261                                 case 2:
7262                                         genc16bit2lit(left,lit,offset);
7263                                         genSkip(ifx,'z');
7264                                         break;
7265                                         /* end of size == 2 */
7266
7267                                 default:
7268                                         /* size is 4 */
7269                                         if(lit==0) {
7270                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7271                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7272                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7273                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7274                                                 genSkip(ifx,'z');
7275                                         } else {
7276                                                 /* search for patterns that can be optimized */
7277
7278                                                 genc16bit2lit(left,lit,0);
7279                                                 lit >>= 16;
7280                                                 if(lit) {
7281                                                                 if(IC_TRUE(ifx))
7282                                                                 emitSKPZ; // if hi word unequal
7283                                                                 else
7284                                                                 emitSKPNZ; // if hi word equal
7285                                                                 // fail early
7286                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7287                                                         genc16bit2lit(left,lit,2);
7288                                                         genSkip(ifx,'z');
7289                                                 } else {
7290                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7291                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7292                                                         genSkip(ifx,'z');
7293                                                 }
7294                                         }
7295                                                 pic16_emitpLabel(falselbl->key);
7296                                                 break;
7297
7298                         } // switch size
7299           
7300                         ifx->generated = 1;
7301                         goto release ;
7302             
7303
7304           } else if(AOP_TYPE(right) == AOP_CRY ) {
7305             /* we know the left is not a bit, but that the right is */
7306             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7307             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7308                       pic16_popGet(AOP(right),offset));
7309             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7310
7311             /* if the two are equal, then W will be 0 and the Z bit is set
7312              * we could test Z now, or go ahead and check the high order bytes if
7313              * the variable we're comparing is larger than a byte. */
7314
7315             while(--size)
7316               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7317
7318             if ( IC_TRUE(ifx) ) {
7319               emitSKPNZ;
7320               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7321               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7322             } else {
7323               emitSKPZ;
7324               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7325               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7326             }
7327
7328           } else {
7329             /* They're both variables that are larger than bits */
7330             int s = size;
7331
7332             tlbl = newiTempLabel(NULL);
7333
7334             while(size--) {
7335               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7336               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7337
7338               if ( IC_TRUE(ifx) ) {
7339                 if(size) {
7340                   emitSKPZ;
7341                 
7342                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7343
7344                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7345                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7346                 } else {
7347                   emitSKPNZ;
7348
7349                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7350
7351
7352                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7353                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7354                 }
7355               } else {
7356                 emitSKPZ;
7357
7358                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7359
7360                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7361                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7362               }
7363               offset++;
7364             }
7365             if(s>1 && IC_TRUE(ifx)) {
7366               pic16_emitpLabel(tlbl->key);
7367               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7368             }
7369           }
7370         }
7371         /* mark the icode as generated */
7372         ifx->generated = 1;
7373         goto release ;
7374     }
7375
7376     /* if they are both bit variables */
7377     if (AOP_TYPE(left) == AOP_CRY &&
7378         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7379         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7380         if(AOP_TYPE(right) == AOP_LIT){
7381             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7382             if(lit == 0L){
7383                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7384                 pic16_emitcode("cpl","c");
7385             } else if(lit == 1L) {
7386                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7387             } else {
7388                 pic16_emitcode("clr","c");
7389             }
7390             /* AOP_TYPE(right) == AOP_CRY */
7391         } else {
7392             symbol *lbl = newiTempLabel(NULL);
7393             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7394             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7395             pic16_emitcode("cpl","c");
7396             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7397         }
7398         /* c = 1 if egal */
7399         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7400             pic16_outBitC(result);
7401             goto release ;
7402         }
7403         if (ifx) {
7404             genIfxJump (ifx,"c");
7405             goto release ;
7406         }
7407         /* if the result is used in an arithmetic operation
7408         then put the result in place */
7409         pic16_outBitC(result);
7410     } else {
7411       
7412       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7413       gencjne(left,right,result,ifx);
7414 /*
7415       if(ifx) 
7416         gencjne(left,right,newiTempLabel(NULL));
7417       else {
7418         if(IC_TRUE(ifx)->key)
7419           gencjne(left,right,IC_TRUE(ifx)->key);
7420         else
7421           gencjne(left,right,IC_FALSE(ifx)->key);
7422         ifx->generated = 1;
7423         goto release ;
7424       }
7425       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7426         pic16_aopPut(AOP(result),"a",0);
7427         goto release ;
7428       }
7429
7430       if (ifx) {
7431         genIfxJump (ifx,"a");
7432         goto release ;
7433       }
7434 */
7435       /* if the result is used in an arithmetic operation
7436          then put the result in place */
7437 /*
7438       if (AOP_TYPE(result) != AOP_CRY) 
7439         pic16_outAcc(result);
7440 */
7441       /* leave the result in acc */
7442     }
7443
7444 release:
7445     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7446     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7447     pic16_freeAsmop(result,NULL,ic,TRUE);
7448 }
7449 #endif
7450
7451 /*-----------------------------------------------------------------*/
7452 /* ifxForOp - returns the icode containing the ifx for operand     */
7453 /*-----------------------------------------------------------------*/
7454 static iCode *ifxForOp ( operand *op, iCode *ic )
7455 {
7456   FENTRY2;
7457
7458     /* if true symbol then needs to be assigned */
7459     if (IS_TRUE_SYMOP(op))
7460         return NULL ;
7461
7462     /* if this has register type condition and
7463     the next instruction is ifx with the same operand
7464     and live to of the operand is upto the ifx only then */
7465     if (ic->next
7466         && ic->next->op == IFX
7467         && IC_COND(ic->next)->key == op->key
7468         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7469         ) {
7470                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7471           return ic->next;
7472     }
7473
7474     /*
7475     if (ic->next &&
7476         ic->next->op == IFX &&
7477         IC_COND(ic->next)->key == op->key) {
7478       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7479       return ic->next;
7480     }
7481     */
7482
7483     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7484     if (ic->next &&
7485         ic->next->op == IFX)
7486       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7487
7488     if (ic->next &&
7489         ic->next->op == IFX &&
7490         IC_COND(ic->next)->key == op->key) {
7491       DEBUGpic16_emitcode ("; "," key is okay");
7492       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7493                            OP_SYMBOL(op)->liveTo,
7494                            ic->next->seq);
7495     }
7496
7497 #if 0
7498     /* the code below is completely untested
7499      * it just allows ulong2fs.c compile -- VR */
7500          
7501     ic = ic->next;
7502     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7503                                         __FILE__, __FUNCTION__, __LINE__);
7504         
7505     /* if this has register type condition and
7506     the next instruction is ifx with the same operand
7507     and live to of the operand is upto the ifx only then */
7508     if (ic->next &&
7509         ic->next->op == IFX &&
7510         IC_COND(ic->next)->key == op->key &&
7511         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7512         return ic->next;
7513
7514     if (ic->next &&
7515         ic->next->op == IFX &&
7516         IC_COND(ic->next)->key == op->key) {
7517       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7518       return ic->next;
7519     }
7520
7521     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7522                                         __FILE__, __FUNCTION__, __LINE__);
7523
7524 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7525 #endif
7526
7527     return NULL;
7528 }
7529 /*-----------------------------------------------------------------*/
7530 /* genAndOp - for && operation                                     */
7531 /*-----------------------------------------------------------------*/
7532 static void genAndOp (iCode *ic)
7533 {
7534   operand *left,*right, *result;
7535 /*     symbol *tlbl; */
7536
7537     FENTRY;
7538
7539     /* note here that && operations that are in an
7540     if statement are taken away by backPatchLabels
7541     only those used in arthmetic operations remain */
7542     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7543     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7544     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7545
7546     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7547
7548     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7549     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7550     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7551
7552     /* if both are bit variables */
7553 /*     if (AOP_TYPE(left) == AOP_CRY && */
7554 /*         AOP_TYPE(right) == AOP_CRY ) { */
7555 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7556 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7557 /*         pic16_outBitC(result); */
7558 /*     } else { */
7559 /*         tlbl = newiTempLabel(NULL); */
7560 /*         pic16_toBoolean(left);     */
7561 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7562 /*         pic16_toBoolean(right); */
7563 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7564 /*         pic16_outBitAcc(result); */
7565 /*     } */
7566
7567     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7568     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7569     pic16_freeAsmop(result,NULL,ic,TRUE);
7570 }
7571
7572
7573 /*-----------------------------------------------------------------*/
7574 /* genOrOp - for || operation                                      */
7575 /*-----------------------------------------------------------------*/
7576 /*
7577   tsd pic port -
7578   modified this code, but it doesn't appear to ever get called
7579 */
7580
7581 static void genOrOp (iCode *ic)
7582 {
7583   operand *left,*right, *result;
7584   symbol *tlbl;
7585
7586     FENTRY;  
7587
7588   /* note here that || operations that are in an
7589     if statement are taken away by backPatchLabels
7590     only those used in arthmetic operations remain */
7591     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7592     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7593     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7594
7595     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7596
7597     /* if both are bit variables */
7598     if (AOP_TYPE(left) == AOP_CRY &&
7599         AOP_TYPE(right) == AOP_CRY ) {
7600       pic16_emitcode("clrc","");
7601       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7602                AOP(left)->aopu.aop_dir,
7603                AOP(left)->aopu.aop_dir);
7604       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7605                AOP(right)->aopu.aop_dir,
7606                AOP(right)->aopu.aop_dir);
7607       pic16_emitcode("setc","");
7608
7609     } else {
7610         tlbl = newiTempLabel(NULL);
7611         pic16_toBoolean(left);
7612         emitSKPZ;
7613         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7614         pic16_toBoolean(right);
7615         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7616
7617         pic16_outBitAcc(result);
7618     }
7619
7620     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7621     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7622     pic16_freeAsmop(result,NULL,ic,TRUE);            
7623 }
7624
7625 /*-----------------------------------------------------------------*/
7626 /* isLiteralBit - test if lit == 2^n                               */
7627 /*-----------------------------------------------------------------*/
7628 static int isLiteralBit(unsigned long lit)
7629 {
7630     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7631     0x100L,0x200L,0x400L,0x800L,
7632     0x1000L,0x2000L,0x4000L,0x8000L,
7633     0x10000L,0x20000L,0x40000L,0x80000L,
7634     0x100000L,0x200000L,0x400000L,0x800000L,
7635     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7636     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7637     int idx;
7638     
7639     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7640     for(idx = 0; idx < 32; idx++)
7641         if(lit == pw[idx])
7642             return idx+1;
7643     return 0;
7644 }
7645
7646 /*-----------------------------------------------------------------*/
7647 /* continueIfTrue -                                                */
7648 /*-----------------------------------------------------------------*/
7649 static void continueIfTrue (iCode *ic)
7650 {
7651   FENTRY;
7652   if(IC_TRUE(ic))
7653     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7654   ic->generated = 1;
7655 }
7656
7657 /*-----------------------------------------------------------------*/
7658 /* jmpIfTrue -                                                     */
7659 /*-----------------------------------------------------------------*/
7660 static void jumpIfTrue (iCode *ic)
7661 {
7662   FENTRY;
7663   if(!IC_TRUE(ic))
7664     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7665   ic->generated = 1;
7666 }
7667
7668 /*-----------------------------------------------------------------*/
7669 /* jmpTrueOrFalse -                                                */
7670 /*-----------------------------------------------------------------*/
7671 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7672 {
7673   // ugly but optimized by peephole
7674   FENTRY;
7675   if(IC_TRUE(ic)){
7676     symbol *nlbl = newiTempLabel(NULL);
7677       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7678       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7679       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7680       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7681   } else {
7682     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7683     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7684   }
7685   ic->generated = 1;
7686 }
7687
7688 /*-----------------------------------------------------------------*/
7689 /* genAnd  - code for and                                          */
7690 /*-----------------------------------------------------------------*/
7691 static void genAnd (iCode *ic, iCode *ifx)
7692 {
7693   operand *left, *right, *result;
7694   int size, offset=0;  
7695   unsigned long lit = 0L;
7696   int bytelit = 0;
7697   resolvedIfx rIfx;
7698
7699     FENTRY;
7700     
7701   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7702   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7703   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7704
7705   resolveIfx(&rIfx,ifx);
7706
7707   /* if left is a literal & right is not then exchange them */
7708   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7709       AOP_NEEDSACC(left)) {
7710     operand *tmp = right ;
7711     right = left;
7712     left = tmp;
7713   }
7714
7715   /* if result = right then exchange them */
7716   if(pic16_sameRegs(AOP(result),AOP(right))){
7717     operand *tmp = right ;
7718     right = left;
7719     left = tmp;
7720   }
7721
7722   /* if right is bit then exchange them */
7723   if (AOP_TYPE(right) == AOP_CRY &&
7724       AOP_TYPE(left) != AOP_CRY){
7725     operand *tmp = right ;
7726     right = left;
7727     left = tmp;
7728   }
7729   if(AOP_TYPE(right) == AOP_LIT)
7730     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7731
7732   size = AOP_SIZE(result);
7733
7734   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7735
7736   // if(bit & yy)
7737   // result = bit & yy;
7738   if (AOP_TYPE(left) == AOP_CRY){
7739     // c = bit & literal;
7740     if(AOP_TYPE(right) == AOP_LIT){
7741       if(lit & 1) {
7742         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7743           // no change
7744           goto release;
7745         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7746       } else {
7747         // bit(result) = 0;
7748         if(size && (AOP_TYPE(result) == AOP_CRY)){
7749           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7750           goto release;
7751         }
7752         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7753           jumpIfTrue(ifx);
7754           goto release;
7755         }
7756         pic16_emitcode("clr","c");
7757       }
7758     } else {
7759       if (AOP_TYPE(right) == AOP_CRY){
7760         // c = bit & bit;
7761         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7762         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7763       } else {
7764         // c = bit & val;
7765         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7766         // c = lsb
7767         pic16_emitcode("rrc","a");
7768         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7769       }
7770     }
7771     // bit = c
7772     // val = c
7773     if(size)
7774       pic16_outBitC(result);
7775     // if(bit & ...)
7776     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7777       genIfxJump(ifx, "c");           
7778     goto release ;
7779   }
7780
7781   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7782   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7783   if((AOP_TYPE(right) == AOP_LIT) &&
7784      (AOP_TYPE(result) == AOP_CRY) &&
7785      (AOP_TYPE(left) != AOP_CRY)){
7786     int posbit = isLiteralBit(lit);
7787     /* left &  2^n */
7788     if(posbit){
7789       posbit--;
7790       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7791       // bit = left & 2^n
7792       if(size)
7793         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7794       // if(left &  2^n)
7795       else{
7796         if(ifx){
7797 /*
7798           if(IC_TRUE(ifx)) {
7799             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7800             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7801           } else {
7802             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7803             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7804           }
7805 */
7806         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7807         size = AOP_SIZE(left);
7808
7809         {
7810           int bp = posbit, ofs=0;
7811           
7812             while(bp > 7) {
7813               bp -= 8;
7814               ofs++;
7815             }
7816         
7817           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7818                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7819
7820         }
7821 /*
7822           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7823                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7824 */
7825           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7826           
7827           ifx->generated = 1;
7828         }
7829         goto release;
7830       }
7831     } else {
7832       symbol *tlbl = newiTempLabel(NULL);
7833       int sizel = AOP_SIZE(left);
7834
7835       if(size)
7836         emitSETC;
7837
7838       while(sizel--) {
7839         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7840
7841           /* patch provided by Aaron Colwell */
7842           if((posbit = isLiteralBit(bytelit)) != 0) {
7843               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7844                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7845                                                 (posbit-1),0, PO_GPR_REGISTER));
7846
7847               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7848 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7849           } else {
7850               if (bytelit == 0xff) {
7851                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7852                    * a peephole could optimize it out -- VR */
7853                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7854               } else {
7855                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7856                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7857               }
7858
7859               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7860                             pic16_popGetLabel(tlbl->key));
7861           }
7862         
7863 #if 0
7864           /* old code, left here for reference -- VR 09/2004 */
7865           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7866           // byte ==  2^n ?
7867           if((posbit = isLiteralBit(bytelit)) != 0)
7868             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7869           else{
7870             if(bytelit != 0x0FFL)
7871               pic16_emitcode("anl","a,%s",
7872                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7873             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7874           }
7875 #endif
7876         }
7877         offset++;
7878       }
7879       // bit = left & literal
7880       if(size) {
7881         emitCLRC;
7882         pic16_emitpLabel(tlbl->key);
7883       }
7884       // if(left & literal)
7885       else {
7886         if(ifx) {
7887           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7888           ifx->generated = 1;
7889         }
7890         pic16_emitpLabel(tlbl->key);
7891         goto release;
7892       }
7893     }
7894
7895     pic16_outBitC(result);
7896     goto release ;
7897   }
7898
7899   /* if left is same as result */
7900   if(pic16_sameRegs(AOP(result),AOP(left))){
7901     int know_W = -1;
7902     for(;size--; offset++,lit>>=8) {
7903       if(AOP_TYPE(right) == AOP_LIT){
7904         switch(lit & 0xff) {
7905         case 0x00:
7906           /*  and'ing with 0 has clears the result */
7907 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7908           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7909           break;
7910         case 0xff:
7911           /* and'ing with 0xff is a nop when the result and left are the same */
7912           break;
7913
7914         default:
7915           {
7916             int p = pic16_my_powof2( (~lit) & 0xff );
7917             if(p>=0) {
7918               /* only one bit is set in the literal, so use a bcf instruction */
7919 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7920               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7921
7922             } else {
7923               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7924               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7925               if(know_W != (lit&0xff))
7926                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7927               know_W = lit &0xff;
7928               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7929             }
7930           }    
7931         }
7932       } else {
7933         if (AOP_TYPE(left) == AOP_ACC) {
7934           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7935         } else {                    
7936           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7937           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7938
7939         }
7940       }
7941     }
7942
7943   } else {
7944     // left & result in different registers
7945     if(AOP_TYPE(result) == AOP_CRY){
7946       // result = bit
7947       // if(size), result in bit
7948       // if(!size && ifx), conditional oper: if(left & right)
7949       symbol *tlbl = newiTempLabel(NULL);
7950       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7951       if(size)
7952         pic16_emitcode("setb","c");
7953       while(sizer--){
7954         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7955         pic16_emitcode("anl","a,%s",
7956                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7957         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7958         offset++;
7959       }
7960       if(size){
7961         CLRC;
7962         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7963         pic16_outBitC(result);
7964       } else if(ifx)
7965         jmpTrueOrFalse(ifx, tlbl);
7966     } else {
7967       for(;(size--);offset++) {
7968         // normal case
7969         // result = left & right
7970         if(AOP_TYPE(right) == AOP_LIT){
7971           int t = (lit >> (offset*8)) & 0x0FFL;
7972           switch(t) { 
7973           case 0x00:
7974             pic16_emitcode("clrf","%s",
7975                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7976             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7977             break;
7978           case 0xff:
7979             pic16_emitcode("movf","%s,w",
7980                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7981             pic16_emitcode("movwf","%s",
7982                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7983             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7984             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7985             break;
7986           default:
7987             pic16_emitcode("movlw","0x%x",t);
7988             pic16_emitcode("andwf","%s,w",
7989                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7990             pic16_emitcode("movwf","%s",
7991                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7992               
7993             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7994             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7995             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7996           }
7997           continue;
7998         }
7999
8000         if (AOP_TYPE(left) == AOP_ACC) {
8001           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8002           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8003         } else {
8004           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8005           pic16_emitcode("andwf","%s,w",
8006                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8007           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8008           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8009         }
8010         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8011         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8012       }
8013     }
8014   }
8015
8016   release :
8017     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8018   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8019   pic16_freeAsmop(result,NULL,ic,TRUE);     
8020 }
8021
8022 /*-----------------------------------------------------------------*/
8023 /* genOr  - code for or                                            */
8024 /*-----------------------------------------------------------------*/
8025 static void genOr (iCode *ic, iCode *ifx)
8026 {
8027     operand *left, *right, *result;
8028     int size, offset=0;
8029     unsigned long lit = 0L;
8030
8031     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8032
8033     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8034     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8035     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8036
8037     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8038
8039     /* if left is a literal & right is not then exchange them */
8040     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8041         AOP_NEEDSACC(left)) {
8042         operand *tmp = right ;
8043         right = left;
8044         left = tmp;
8045     }
8046
8047     /* if result = right then exchange them */
8048     if(pic16_sameRegs(AOP(result),AOP(right))){
8049         operand *tmp = right ;
8050         right = left;
8051         left = tmp;
8052     }
8053
8054     /* if right is bit then exchange them */
8055     if (AOP_TYPE(right) == AOP_CRY &&
8056         AOP_TYPE(left) != AOP_CRY){
8057         operand *tmp = right ;
8058         right = left;
8059         left = tmp;
8060     }
8061
8062     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8063
8064     if(AOP_TYPE(right) == AOP_LIT)
8065         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8066
8067     size = AOP_SIZE(result);
8068
8069     // if(bit | yy)
8070     // xx = bit | yy;
8071     if (AOP_TYPE(left) == AOP_CRY){
8072         if(AOP_TYPE(right) == AOP_LIT){
8073             // c = bit & literal;
8074             if(lit){
8075                 // lit != 0 => result = 1
8076                 if(AOP_TYPE(result) == AOP_CRY){
8077                   if(size)
8078                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8079                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8080                   //     AOP(result)->aopu.aop_dir,
8081                   //     AOP(result)->aopu.aop_dir);
8082                     else if(ifx)
8083                         continueIfTrue(ifx);
8084                     goto release;
8085                 }
8086             } else {
8087                 // lit == 0 => result = left
8088                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8089                     goto release;
8090                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8091             }
8092         } else {
8093             if (AOP_TYPE(right) == AOP_CRY){
8094               if(pic16_sameRegs(AOP(result),AOP(left))){
8095                 // c = bit | bit;
8096                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8097                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8098                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8099
8100                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8101                          AOP(result)->aopu.aop_dir,
8102                          AOP(result)->aopu.aop_dir);
8103                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8104                          AOP(right)->aopu.aop_dir,
8105                          AOP(right)->aopu.aop_dir);
8106                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8107                          AOP(result)->aopu.aop_dir,
8108                          AOP(result)->aopu.aop_dir);
8109               } else {
8110                 if( AOP_TYPE(result) == AOP_ACC) {
8111                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8112                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8113                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8114                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8115
8116                 } else {
8117
8118                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8119                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8120                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8121                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8122
8123                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8124                                  AOP(result)->aopu.aop_dir,
8125                                  AOP(result)->aopu.aop_dir);
8126                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8127                                  AOP(right)->aopu.aop_dir,
8128                                  AOP(right)->aopu.aop_dir);
8129                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8130                                  AOP(left)->aopu.aop_dir,
8131                                  AOP(left)->aopu.aop_dir);
8132                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8133                                  AOP(result)->aopu.aop_dir,
8134                                  AOP(result)->aopu.aop_dir);
8135                 }
8136               }
8137             } else {
8138                 // c = bit | val;
8139                 symbol *tlbl = newiTempLabel(NULL);
8140                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8141
8142
8143                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8144                 if( AOP_TYPE(right) == AOP_ACC) {
8145                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8146                   emitSKPNZ;
8147                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8148                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8149                 }
8150
8151
8152
8153                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8154                     pic16_emitcode(";XXX setb","c");
8155                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8156                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8157                 pic16_toBoolean(right);
8158                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8159                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8160                     jmpTrueOrFalse(ifx, tlbl);
8161                     goto release;
8162                 } else {
8163                     CLRC;
8164                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8165                 }
8166             }
8167         }
8168         // bit = c
8169         // val = c
8170         if(size)
8171             pic16_outBitC(result);
8172         // if(bit | ...)
8173         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8174             genIfxJump(ifx, "c");           
8175         goto release ;
8176     }
8177
8178     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8179     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8180     if((AOP_TYPE(right) == AOP_LIT) &&
8181        (AOP_TYPE(result) == AOP_CRY) &&
8182        (AOP_TYPE(left) != AOP_CRY)){
8183         if(lit){
8184           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8185             // result = 1
8186             if(size)
8187                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8188             else 
8189                 continueIfTrue(ifx);
8190             goto release;
8191         } else {
8192           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8193             // lit = 0, result = boolean(left)
8194             if(size)
8195                 pic16_emitcode(";XXX setb","c");
8196             pic16_toBoolean(right);
8197             if(size){
8198                 symbol *tlbl = newiTempLabel(NULL);
8199                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8200                 CLRC;
8201                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8202             } else {
8203                 genIfxJump (ifx,"a");
8204                 goto release;
8205             }
8206         }
8207         pic16_outBitC(result);
8208         goto release ;
8209     }
8210
8211     /* if left is same as result */
8212     if(pic16_sameRegs(AOP(result),AOP(left))){
8213       int know_W = -1;
8214       for(;size--; offset++,lit>>=8) {
8215         if(AOP_TYPE(right) == AOP_LIT){
8216           if((lit & 0xff) == 0)
8217             /*  or'ing with 0 has no effect */
8218             continue;
8219           else {
8220             int p = pic16_my_powof2(lit & 0xff);
8221             if(p>=0) {
8222               /* only one bit is set in the literal, so use a bsf instruction */
8223               pic16_emitpcode(POC_BSF,
8224                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8225             } else {
8226               if(know_W != (lit & 0xff))
8227                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8228               know_W = lit & 0xff;
8229               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8230             }
8231                     
8232           }
8233         } else {
8234           if (AOP_TYPE(left) == AOP_ACC) {
8235             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8236             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8237           } else {                  
8238             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8239             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8240
8241             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8242             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8243
8244           }
8245         }
8246       }
8247     } else {
8248         // left & result in different registers
8249         if(AOP_TYPE(result) == AOP_CRY){
8250             // result = bit
8251             // if(size), result in bit
8252             // if(!size && ifx), conditional oper: if(left | right)
8253             symbol *tlbl = newiTempLabel(NULL);
8254             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8255             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8256
8257
8258             if(size)
8259                 pic16_emitcode(";XXX setb","c");
8260             while(sizer--){
8261                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8262                 pic16_emitcode(";XXX orl","a,%s",
8263                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8264                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8265                 offset++;
8266             }
8267             if(size){
8268                 CLRC;
8269                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8270                 pic16_outBitC(result);
8271             } else if(ifx)
8272                 jmpTrueOrFalse(ifx, tlbl);
8273         } else for(;(size--);offset++){
8274           // normal case
8275           // result = left & right
8276           if(AOP_TYPE(right) == AOP_LIT){
8277             int t = (lit >> (offset*8)) & 0x0FFL;
8278             switch(t) { 
8279             case 0x00:
8280               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8281               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8282
8283               pic16_emitcode("movf","%s,w",
8284                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8285               pic16_emitcode("movwf","%s",
8286                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8287               break;
8288             default:
8289               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8290               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8291               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8292
8293               pic16_emitcode("movlw","0x%x",t);
8294               pic16_emitcode("iorwf","%s,w",
8295                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8296               pic16_emitcode("movwf","%s",
8297                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8298               
8299             }
8300             continue;
8301           }
8302
8303           // faster than result <- left, anl result,right
8304           // and better if result is SFR
8305           if (AOP_TYPE(left) == AOP_ACC) {
8306             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8307             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8308           } else {
8309             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8310             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8311
8312             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8313             pic16_emitcode("iorwf","%s,w",
8314                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8315           }
8316           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8317           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8318         }
8319     }
8320
8321 release :
8322     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8323     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8324     pic16_freeAsmop(result,NULL,ic,TRUE);     
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* genXor - code for xclusive or                                   */
8329 /*-----------------------------------------------------------------*/
8330 static void genXor (iCode *ic, iCode *ifx)
8331 {
8332   operand *left, *right, *result;
8333   int size, offset=0;
8334   unsigned long lit = 0L;
8335
8336   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8337
8338   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8339   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8340   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8341
8342   /* if left is a literal & right is not ||
8343      if left needs acc & right does not */
8344   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8345       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8346     operand *tmp = right ;
8347     right = left;
8348     left = tmp;
8349   }
8350
8351   /* if result = right then exchange them */
8352   if(pic16_sameRegs(AOP(result),AOP(right))){
8353     operand *tmp = right ;
8354     right = left;
8355     left = tmp;
8356   }
8357
8358   /* if right is bit then exchange them */
8359   if (AOP_TYPE(right) == AOP_CRY &&
8360       AOP_TYPE(left) != AOP_CRY){
8361     operand *tmp = right ;
8362     right = left;
8363     left = tmp;
8364   }
8365   if(AOP_TYPE(right) == AOP_LIT)
8366     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8367
8368   size = AOP_SIZE(result);
8369
8370   // if(bit ^ yy)
8371   // xx = bit ^ yy;
8372   if (AOP_TYPE(left) == AOP_CRY){
8373     if(AOP_TYPE(right) == AOP_LIT){
8374       // c = bit & literal;
8375       if(lit>>1){
8376         // lit>>1  != 0 => result = 1
8377         if(AOP_TYPE(result) == AOP_CRY){
8378           if(size)
8379             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8380             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8381           else if(ifx)
8382             continueIfTrue(ifx);
8383           goto release;
8384         }
8385         pic16_emitcode("setb","c");
8386       } else{
8387         // lit == (0 or 1)
8388         if(lit == 0){
8389           // lit == 0, result = left
8390           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8391             goto release;
8392           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8393         } else{
8394           // lit == 1, result = not(left)
8395           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8396             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8397             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8398             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8399             goto release;
8400           } else {
8401             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8402             pic16_emitcode("cpl","c");
8403           }
8404         }
8405       }
8406
8407     } else {
8408       // right != literal
8409       symbol *tlbl = newiTempLabel(NULL);
8410       if (AOP_TYPE(right) == AOP_CRY){
8411         // c = bit ^ bit;
8412         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8413       }
8414       else{
8415         int sizer = AOP_SIZE(right);
8416         // c = bit ^ val
8417         // if val>>1 != 0, result = 1
8418         pic16_emitcode("setb","c");
8419         while(sizer){
8420           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8421           if(sizer == 1)
8422             // test the msb of the lsb
8423             pic16_emitcode("anl","a,#0xfe");
8424           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8425           sizer--;
8426         }
8427         // val = (0,1)
8428         pic16_emitcode("rrc","a");
8429       }
8430       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8431       pic16_emitcode("cpl","c");
8432       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8433     }
8434     // bit = c
8435     // val = c
8436     if(size)
8437       pic16_outBitC(result);
8438     // if(bit | ...)
8439     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8440       genIfxJump(ifx, "c");           
8441     goto release ;
8442   }
8443
8444   if(pic16_sameRegs(AOP(result),AOP(left))){
8445     /* if left is same as result */
8446     for(;size--; offset++) {
8447       if(AOP_TYPE(right) == AOP_LIT){
8448         int t  = (lit >> (offset*8)) & 0x0FFL;
8449         if(t == 0x00L)
8450           continue;
8451         else
8452           if (IS_AOP_PREG(left)) {
8453             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8454             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8455             pic16_aopPut(AOP(result),"a",offset);
8456           } else {
8457             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8458             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8459             pic16_emitcode("xrl","%s,%s",
8460                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8461                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8462           }
8463       } else {
8464         if (AOP_TYPE(left) == AOP_ACC)
8465           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8466         else {
8467           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8468           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8469 /*
8470           if (IS_AOP_PREG(left)) {
8471             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8472             pic16_aopPut(AOP(result),"a",offset);
8473           } else
8474             pic16_emitcode("xrl","%s,a",
8475                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8476 */
8477         }
8478       }
8479     }
8480   } else {
8481     // left & result in different registers
8482     if(AOP_TYPE(result) == AOP_CRY){
8483       // result = bit
8484       // if(size), result in bit
8485       // if(!size && ifx), conditional oper: if(left ^ right)
8486       symbol *tlbl = newiTempLabel(NULL);
8487       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8488       if(size)
8489         pic16_emitcode("setb","c");
8490       while(sizer--){
8491         if((AOP_TYPE(right) == AOP_LIT) &&
8492            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8493           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8494         } else {
8495           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8496           pic16_emitcode("xrl","a,%s",
8497                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8498         }
8499         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8500         offset++;
8501       }
8502       if(size){
8503         CLRC;
8504         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8505         pic16_outBitC(result);
8506       } else if(ifx)
8507         jmpTrueOrFalse(ifx, tlbl);
8508     } else for(;(size--);offset++){
8509       // normal case
8510       // result = left & right
8511       if(AOP_TYPE(right) == AOP_LIT){
8512         int t = (lit >> (offset*8)) & 0x0FFL;
8513         switch(t) { 
8514         case 0x00:
8515           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8516           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8517           pic16_emitcode("movf","%s,w",
8518                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8519           pic16_emitcode("movwf","%s",
8520                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8521           break;
8522         case 0xff:
8523           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8524           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8525           pic16_emitcode("comf","%s,w",
8526                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8527           pic16_emitcode("movwf","%s",
8528                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8529           break;
8530         default:
8531           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8532           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8533           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8534           pic16_emitcode("movlw","0x%x",t);
8535           pic16_emitcode("xorwf","%s,w",
8536                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8537           pic16_emitcode("movwf","%s",
8538                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8539
8540         }
8541         continue;
8542       }
8543
8544       // faster than result <- left, anl result,right
8545       // and better if result is SFR
8546       if (AOP_TYPE(left) == AOP_ACC) {
8547         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8548         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8549       } else {
8550         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8551         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8552         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8553         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8554       }
8555       if ( AOP_TYPE(result) != AOP_ACC){
8556         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8557         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8558       }
8559     }
8560   }
8561
8562   release :
8563     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8564   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8565   pic16_freeAsmop(result,NULL,ic,TRUE);     
8566 }
8567
8568 /*-----------------------------------------------------------------*/
8569 /* genInline - write the inline code out                           */
8570 /*-----------------------------------------------------------------*/
8571 static void genInline (iCode *ic)
8572 {
8573   char *buffer, *bp, *bp1;
8574     
8575         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8576
8577         _G.inLine += (!options.asmpeep);
8578
8579         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8580         strcpy(buffer,IC_INLINE(ic));
8581
8582 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8583
8584         /* emit each line as a code */
8585         while (*bp) {
8586                 if (*bp == '\n') {
8587                         *bp++ = '\0';
8588
8589                         if(*bp1)
8590                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8591                         bp1 = bp;
8592                 } else {
8593                         if (*bp == ':') {
8594                                 bp++;
8595                                 *bp = '\0';
8596                                 bp++;
8597
8598                                 /* print label, use this special format with NULL directive
8599                                  * to denote that the argument should not be indented with tab */
8600                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8601                                 bp1 = bp;
8602                         } else
8603                                 bp++;
8604                 }
8605         }
8606
8607         if ((bp1 != bp) && *bp1)
8608                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8609
8610
8611     Safe_free(buffer);
8612
8613     _G.inLine -= (!options.asmpeep);
8614 }
8615
8616 /*-----------------------------------------------------------------*/
8617 /* genRRC - rotate right with carry                                */
8618 /*-----------------------------------------------------------------*/
8619 static void genRRC (iCode *ic)
8620 {
8621   operand *left , *result ;
8622   int size, offset = 0, same;
8623
8624   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8625
8626   /* rotate right with carry */
8627   left = IC_LEFT(ic);
8628   result=IC_RESULT(ic);
8629   pic16_aopOp (left,ic,FALSE);
8630   pic16_aopOp (result,ic,FALSE);
8631
8632   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8633
8634   same = pic16_sameRegs(AOP(result),AOP(left));
8635
8636   size = AOP_SIZE(result);    
8637
8638   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8639
8640   /* get the lsb and put it into the carry */
8641   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8642
8643   offset = 0 ;
8644
8645   while(size--) {
8646
8647     if(same) {
8648       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8649     } else {
8650       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8651       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8652     }
8653
8654     offset++;
8655   }
8656
8657   pic16_freeAsmop(left,NULL,ic,TRUE);
8658   pic16_freeAsmop(result,NULL,ic,TRUE);
8659 }
8660
8661 /*-----------------------------------------------------------------*/
8662 /* genRLC - generate code for rotate left with carry               */
8663 /*-----------------------------------------------------------------*/
8664 static void genRLC (iCode *ic)
8665 {    
8666   operand *left , *result ;
8667   int size, offset = 0;
8668   int same;
8669
8670   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8671   /* rotate right with carry */
8672   left = IC_LEFT(ic);
8673   result=IC_RESULT(ic);
8674   pic16_aopOp (left,ic,FALSE);
8675   pic16_aopOp (result,ic,FALSE);
8676
8677   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8678
8679   same = pic16_sameRegs(AOP(result),AOP(left));
8680
8681   /* move it to the result */
8682   size = AOP_SIZE(result);    
8683
8684   /* get the msb and put it into the carry */
8685   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8686
8687   offset = 0 ;
8688
8689   while(size--) {
8690
8691     if(same) {
8692       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8693     } else {
8694       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8695       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8696     }
8697
8698     offset++;
8699   }
8700
8701
8702   pic16_freeAsmop(left,NULL,ic,TRUE);
8703   pic16_freeAsmop(result,NULL,ic,TRUE);
8704 }
8705
8706
8707 /* gpasm can get the highest order bit with HIGH/UPPER
8708  * so the following probably is not needed -- VR */
8709  
8710 /*-----------------------------------------------------------------*/
8711 /* genGetHbit - generates code get highest order bit               */
8712 /*-----------------------------------------------------------------*/
8713 static void genGetHbit (iCode *ic)
8714 {
8715     operand *left, *result;
8716     left = IC_LEFT(ic);
8717     result=IC_RESULT(ic);
8718     pic16_aopOp (left,ic,FALSE);
8719     pic16_aopOp (result,ic,FALSE);
8720
8721     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8722     /* get the highest order byte into a */
8723     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8724     if(AOP_TYPE(result) == AOP_CRY){
8725         pic16_emitcode("rlc","a");
8726         pic16_outBitC(result);
8727     }
8728     else{
8729         pic16_emitcode("rl","a");
8730         pic16_emitcode("anl","a,#0x01");
8731         pic16_outAcc(result);
8732     }
8733
8734
8735     pic16_freeAsmop(left,NULL,ic,TRUE);
8736     pic16_freeAsmop(result,NULL,ic,TRUE);
8737 }
8738
8739 #if 0
8740 /*-----------------------------------------------------------------*/
8741 /* AccRol - rotate left accumulator by known count                 */
8742 /*-----------------------------------------------------------------*/
8743 static void AccRol (int shCount)
8744 {
8745     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746     shCount &= 0x0007;              // shCount : 0..7
8747     switch(shCount){
8748         case 0 :
8749             break;
8750         case 1 :
8751             pic16_emitcode("rl","a");
8752             break;
8753         case 2 :
8754             pic16_emitcode("rl","a");
8755             pic16_emitcode("rl","a");
8756             break;
8757         case 3 :
8758             pic16_emitcode("swap","a");
8759             pic16_emitcode("rr","a");
8760             break;
8761         case 4 :
8762             pic16_emitcode("swap","a");
8763             break;
8764         case 5 :
8765             pic16_emitcode("swap","a");
8766             pic16_emitcode("rl","a");
8767             break;
8768         case 6 :
8769             pic16_emitcode("rr","a");
8770             pic16_emitcode("rr","a");
8771             break;
8772         case 7 :
8773             pic16_emitcode("rr","a");
8774             break;
8775     }
8776 }
8777 #endif
8778
8779 /*-----------------------------------------------------------------*/
8780 /* AccLsh - left shift accumulator by known count                  */
8781 /*-----------------------------------------------------------------*/
8782 static void AccLsh (int shCount)
8783 {
8784         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8785         switch(shCount){
8786                 case 0 :
8787                         return;
8788                         break;
8789                 case 1 :
8790                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8791                         break;
8792                 case 2 :
8793                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8794                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8795                         break;
8796                 case 3 :
8797                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8798                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8799                         break;
8800                 case 4 :
8801                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8802                         break;
8803                 case 5 :
8804                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8805                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8806                         break;
8807                 case 6 :
8808                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8809                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8810                         break;
8811                 case 7 :
8812                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8813                         break;
8814         }
8815
8816         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8817 }
8818
8819 /*-----------------------------------------------------------------*/
8820 /* AccRsh - right shift accumulator by known count                 */
8821 /*-----------------------------------------------------------------*/
8822 static void AccRsh (int shCount, int andmask)
8823 {
8824         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825         switch(shCount){
8826                 case 0 :
8827                         return; break;
8828                 case 1 :
8829                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830                         break;
8831                 case 2 :
8832                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8834                         break;
8835                 case 3 :
8836                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8837                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8838                         break;
8839                 case 4 :
8840                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8841                         break;
8842                 case 5 :
8843                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8844                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8845                         break;
8846                 case 6 :
8847                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8848                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8849                         break;
8850                 case 7 :
8851                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8852                         break;
8853         }
8854         
8855         if(andmask)
8856                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8857         else
8858                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8859 }
8860
8861 #if 0
8862 /*-----------------------------------------------------------------*/
8863 /* AccSRsh - signed right shift accumulator by known count                 */
8864 /*-----------------------------------------------------------------*/
8865 static void AccSRsh (int shCount)
8866 {
8867     symbol *tlbl ;
8868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8869     if(shCount != 0){
8870         if(shCount == 1){
8871             pic16_emitcode("mov","c,acc.7");
8872             pic16_emitcode("rrc","a");
8873         } else if(shCount == 2){
8874             pic16_emitcode("mov","c,acc.7");
8875             pic16_emitcode("rrc","a");
8876             pic16_emitcode("mov","c,acc.7");
8877             pic16_emitcode("rrc","a");
8878         } else {
8879             tlbl = newiTempLabel(NULL);
8880             /* rotate right accumulator */
8881             AccRol(8 - shCount);
8882             /* and kill the higher order bits */
8883             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8884             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8885             pic16_emitcode("orl","a,#0x%02x",
8886                      (unsigned char)~SRMask[shCount]);
8887             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8888         }
8889     }
8890 }
8891 #endif
8892
8893 /*-----------------------------------------------------------------*/
8894 /* shiftR1Left2Result - shift right one byte from left to result   */
8895 /*-----------------------------------------------------------------*/
8896 static void shiftR1Left2ResultSigned (operand *left, int offl,
8897                                 operand *result, int offr,
8898                                 int shCount)
8899 {
8900   int same;
8901
8902   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8903
8904   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8905
8906   switch(shCount) {
8907   case 1:
8908     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8909     if(same) 
8910       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8911     else {
8912       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8913       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914     }
8915
8916     break;
8917   case 2:
8918
8919     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8920     if(same) 
8921       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8922     else {
8923       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8924       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8925     }
8926     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8927     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8928
8929     break;
8930
8931   case 3:
8932     if(same)
8933       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8934     else {
8935       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8936       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8937     }
8938
8939     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8940     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8941     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8942
8943     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8944     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8945
8946     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947     break;
8948
8949   case 4:
8950     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8951     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8952     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8954     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8955     break;
8956   case 5:
8957     if(same) {
8958       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8959     } else {
8960       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8961       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8962     }
8963     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8964     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8965     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8966     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8967     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8968     break;
8969
8970   case 6:
8971     if(same) {
8972       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8973       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8975       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8976       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8977       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8978     } else {
8979       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8981       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8983       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8984     }
8985     break;
8986
8987   case 7:
8988     if(same) {
8989       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8990       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8991       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8992       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993     } else {
8994       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8996       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8997     }
8998
8999   default:
9000     break;
9001   }
9002 }
9003
9004 /*-----------------------------------------------------------------*/
9005 /* shiftR1Left2Result - shift right one byte from left to result   */
9006 /*-----------------------------------------------------------------*/
9007 static void shiftR1Left2Result (operand *left, int offl,
9008                                 operand *result, int offr,
9009                                 int shCount, int sign)
9010 {
9011   int same;
9012
9013   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9014
9015   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9016
9017   /* Copy the msb into the carry if signed. */
9018   if(sign) {
9019     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9020     return;
9021   }
9022
9023
9024
9025   switch(shCount) {
9026   case 1:
9027     emitCLRC;
9028     if(same) 
9029       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9030     else {
9031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9032       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9033     }
9034     break;
9035   case 2:
9036     emitCLRC;
9037     if(same) {
9038       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9039     } else {
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9041       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9042     }
9043     emitCLRC;
9044     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9045
9046     break;
9047   case 3:
9048     if(same)
9049       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9050     else {
9051       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9052       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9053     }
9054
9055     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9056     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9057     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9058     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9059     break;
9060       
9061   case 4:
9062     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9063     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9064     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9065     break;
9066
9067   case 5:
9068     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9069     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9070     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9071     //emitCLRC;
9072     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9073
9074     break;
9075   case 6:
9076
9077     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9078     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9079     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9080     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9081     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9082     break;
9083
9084   case 7:
9085
9086     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9087     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9088     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9089
9090     break;
9091
9092   default:
9093     break;
9094   }
9095 }
9096
9097 /*-----------------------------------------------------------------*/
9098 /* shiftL1Left2Result - shift left one byte from left to result    */
9099 /*-----------------------------------------------------------------*/
9100 static void shiftL1Left2Result (operand *left, int offl,
9101                                 operand *result, int offr, int shCount)
9102 {
9103   int same;
9104
9105   //    char *l;
9106   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9107
9108   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9109   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9110     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9111     //    MOVA(l);
9112     /* shift left accumulator */
9113     //AccLsh(shCount); // don't comment out just yet...
9114   //    pic16_aopPut(AOP(result),"a",offr);
9115
9116   switch(shCount) {
9117   case 1:
9118     /* Shift left 1 bit position */
9119     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9120     if(same) {
9121       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9122     } else {
9123       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9124       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9125     }
9126     break;
9127   case 2:
9128     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9129     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9130     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9131     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9132     break;
9133   case 3:
9134     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9135     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9136     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9137     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9138     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9139     break;
9140   case 4:
9141     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9142     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9143     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9144     break;
9145   case 5:
9146     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9147     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9148     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9149     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9150     break;
9151   case 6:
9152     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9153     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9154     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9156     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9157     break;
9158   case 7:
9159     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9160     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9161     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9162     break;
9163
9164   default:
9165     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9166   }
9167
9168 }
9169
9170 /*-----------------------------------------------------------------*/
9171 /* movLeft2Result - move byte from left to result                  */
9172 /*-----------------------------------------------------------------*/
9173 static void movLeft2Result (operand *left, int offl,
9174                             operand *result, int offr)
9175 {
9176   char *l;
9177   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9178   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9179     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9180
9181     if (*l == '@' && (IS_AOP_PREG(result))) {
9182       pic16_emitcode("mov","a,%s",l);
9183       pic16_aopPut(AOP(result),"a",offr);
9184     } else {
9185       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9186       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9187     }
9188   }
9189 }
9190
9191 /*-----------------------------------------------------------------*/
9192 /* shiftL2Left2Result - shift left two bytes from left to result   */
9193 /*-----------------------------------------------------------------*/
9194 static void shiftL2Left2Result (operand *left, int offl,
9195                                 operand *result, int offr, int shCount)
9196 {
9197   int same = pic16_sameRegs(AOP(result), AOP(left));
9198   int i;
9199
9200   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9201
9202   if (same && (offl != offr)) { // shift bytes
9203     if (offr > offl) {
9204        for(i=1;i>-1;i--) {
9205          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9206          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9207        }
9208     } else { // just treat as different later on
9209                 same = 0;
9210     }
9211   }
9212
9213   if(same) {
9214     switch(shCount) {
9215     case 0:
9216       break;
9217     case 1:
9218     case 2:
9219     case 3:
9220
9221       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9222       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9223       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9224
9225       while(--shCount) {
9226                 emitCLRC;
9227                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9228                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9229       }
9230
9231       break;
9232     case 4:
9233     case 5:
9234       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9235       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9236       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9237       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9239       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9240       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9241       if(shCount >=5) {
9242                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9243                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9244       }
9245       break;
9246     case 6:
9247       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9248       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9249       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9250       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9251       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9252       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9253       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9254       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9255       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9256       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9257       break;
9258     case 7:
9259       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9260       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9261       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9262       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9263       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9264     }
9265
9266   } else {
9267     switch(shCount) {
9268     case 0:
9269       break;
9270     case 1:
9271     case 2:
9272     case 3:
9273       /* note, use a mov/add for the shift since the mov has a
9274          chance of getting optimized out */
9275       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9276       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9277       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9278       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9280
9281       while(--shCount) {
9282                 emitCLRC;
9283                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9284                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9285       }
9286       break;
9287
9288     case 4:
9289     case 5:
9290       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9291       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9292       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9293       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9294       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9295       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9296       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9297       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9298
9299
9300       if(shCount == 5) {
9301                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9302                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9303       }
9304       break;
9305     case 6:
9306       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9307       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9308       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9309       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9310
9311       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9312       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9313       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9314       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9315       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9316       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9317       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9318       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9319       break;
9320     case 7:
9321       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9322       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9323       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9324       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9325       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9326     }
9327   }
9328
9329 }
9330 /*-----------------------------------------------------------------*/
9331 /* shiftR2Left2Result - shift right two bytes from left to result  */
9332 /*-----------------------------------------------------------------*/
9333 static void shiftR2Left2Result (operand *left, int offl,
9334                                 operand *result, int offr,
9335                                 int shCount, int sign)
9336 {
9337   int same = pic16_sameRegs(AOP(result), AOP(left));
9338   int i;
9339   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9340
9341   if (same && (offl != offr)) { // shift right bytes
9342     if (offr < offl) {
9343        for(i=0;i<2;i++) {
9344          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9345          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9346        }
9347     } else { // just treat as different later on
9348                 same = 0;
9349     }
9350   }
9351
9352   switch(shCount) {
9353   case 0:
9354     break;
9355   case 1:
9356   case 2:
9357   case 3:
9358     if(sign)
9359       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9360     else
9361       emitCLRC;
9362
9363     if(same) {
9364       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9365       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9366     } else {
9367       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9368       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9370       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9371     }
9372
9373     while(--shCount) {
9374       if(sign)
9375                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9376       else
9377                 emitCLRC;
9378       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9379       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9380     }
9381     break;
9382   case 4:
9383   case 5:
9384     if(same) {
9385
9386       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9387       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9388       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9389
9390       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9391       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9392       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9393       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9394     } else {
9395       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9396       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9397       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9398
9399       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9400       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9401       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9402       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9403       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9404     }
9405
9406     if(shCount >=5) {
9407       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9408       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9409     }
9410
9411     if(sign) {
9412       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9413       pic16_emitpcode(POC_BTFSC, 
9414                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9415       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9416     }
9417
9418     break;
9419
9420   case 6:
9421     if(same) {
9422
9423       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9424       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9425
9426       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9427       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9428       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9429       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9430       if(sign) {
9431         pic16_emitpcode(POC_BTFSC, 
9432                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9433         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9434       }
9435       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9436       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9437       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9438       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9439     } else {
9440       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9441       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9442       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9443       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9444       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9445       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9446       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9447       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9448       if(sign) {
9449         pic16_emitpcode(POC_BTFSC, 
9450                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9451         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9452       }
9453       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9454       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9455
9456         
9457     }
9458
9459     break;
9460   case 7:
9461     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9462     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9463     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9464     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9465     if(sign) {
9466       emitSKPNC;
9467       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9468     } else 
9469       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9470   }
9471 }
9472
9473
9474 /*-----------------------------------------------------------------*/
9475 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9476 /*-----------------------------------------------------------------*/
9477 static void shiftLLeftOrResult (operand *left, int offl,
9478                                 operand *result, int offr, int shCount)
9479 {
9480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9481
9482     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9483     /* shift left accumulator */
9484     AccLsh(shCount);
9485     /* or with result */
9486     /* back to result */
9487     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9488 }
9489
9490 /*-----------------------------------------------------------------*/
9491 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9492 /*-----------------------------------------------------------------*/
9493 static void shiftRLeftOrResult (operand *left, int offl,
9494                                 operand *result, int offr, int shCount)
9495 {
9496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497     
9498     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9499     /* shift right accumulator */
9500     AccRsh(shCount, 1);
9501     /* or with result */
9502     /* back to result */
9503     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9504 }
9505
9506 /*-----------------------------------------------------------------*/
9507 /* genlshOne - left shift a one byte quantity by known count       */
9508 /*-----------------------------------------------------------------*/
9509 static void genlshOne (operand *result, operand *left, int shCount)
9510 {       
9511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9512     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9513 }
9514
9515 /*-----------------------------------------------------------------*/
9516 /* genlshTwo - left shift two bytes by known amount != 0           */
9517 /*-----------------------------------------------------------------*/
9518 static void genlshTwo (operand *result,operand *left, int shCount)
9519 {
9520     int size;
9521     
9522     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9523     size = pic16_getDataSize(result);
9524
9525     /* if shCount >= 8 */
9526     if (shCount >= 8) {
9527         shCount -= 8 ;
9528
9529         if (size > 1){
9530             if (shCount)
9531                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9532             else 
9533                 movLeft2Result(left, LSB, result, MSB16);
9534         }
9535         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9536     }
9537
9538     /*  1 <= shCount <= 7 */
9539     else {  
9540         if(size == 1)
9541             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9542         else 
9543             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9544     }
9545 }
9546
9547 /*-----------------------------------------------------------------*/
9548 /* shiftLLong - shift left one long from left to result            */
9549 /* offr = LSB or MSB16                                             */
9550 /*-----------------------------------------------------------------*/
9551 static void shiftLLong (operand *left, operand *result, int offr )
9552 {
9553     int size = AOP_SIZE(result);
9554     int same = pic16_sameRegs(AOP(left),AOP(result));
9555         int i;
9556
9557     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9558
9559         if (same && (offr == MSB16)) { //shift one byte
9560                 for(i=size-1;i>=MSB16;i--) {
9561                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9562                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9563                 }
9564         } else {
9565                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9566         }
9567         
9568     if (size > LSB+offr ){
9569                 if (same) {
9570                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9571                 } else {
9572                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9573                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9574                 }
9575          }
9576
9577     if(size > MSB16+offr){
9578                 if (same) {
9579                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9580                 } else {
9581                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9582                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9583                 }
9584     }
9585
9586     if(size > MSB24+offr){
9587                 if (same) {
9588                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9589                 } else {
9590                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9591                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9592                 }
9593     }
9594
9595     if(size > MSB32+offr){
9596                 if (same) {
9597                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9598                 } else {
9599                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9600                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9601                 }
9602     }
9603     if(offr != LSB)
9604                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9605
9606 }
9607
9608 /*-----------------------------------------------------------------*/
9609 /* genlshFour - shift four byte by a known amount != 0             */
9610 /*-----------------------------------------------------------------*/
9611 static void genlshFour (operand *result, operand *left, int shCount)
9612 {
9613     int size;
9614
9615     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9616     size = AOP_SIZE(result);
9617
9618     /* if shifting more that 3 bytes */
9619     if (shCount >= 24 ) {
9620         shCount -= 24;
9621         if (shCount)
9622             /* lowest order of left goes to the highest
9623             order of the destination */
9624             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9625         else
9626             movLeft2Result(left, LSB, result, MSB32);
9627
9628                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9629                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9630                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9631
9632         return;
9633     }
9634
9635     /* more than two bytes */
9636     else if ( shCount >= 16 ) {
9637         /* lower order two bytes goes to higher order two bytes */
9638         shCount -= 16;
9639         /* if some more remaining */
9640         if (shCount)
9641             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9642         else {
9643             movLeft2Result(left, MSB16, result, MSB32);
9644             movLeft2Result(left, LSB, result, MSB24);
9645         }
9646                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9647                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9648         return;
9649     }    
9650
9651     /* if more than 1 byte */
9652     else if ( shCount >= 8 ) {
9653         /* lower order three bytes goes to higher order  three bytes */
9654         shCount -= 8;
9655         if(size == 2){
9656             if(shCount)
9657                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9658             else
9659                 movLeft2Result(left, LSB, result, MSB16);
9660         }
9661         else{   /* size = 4 */
9662             if(shCount == 0){
9663                 movLeft2Result(left, MSB24, result, MSB32);
9664                 movLeft2Result(left, MSB16, result, MSB24);
9665                 movLeft2Result(left, LSB, result, MSB16);
9666                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9667             }
9668             else if(shCount == 1)
9669                 shiftLLong(left, result, MSB16);
9670             else{
9671                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9672                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9673                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9674                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9675             }
9676         }
9677     }
9678
9679     /* 1 <= shCount <= 7 */
9680     else if(shCount <= 3)
9681     { 
9682         shiftLLong(left, result, LSB);
9683         while(--shCount >= 1)
9684             shiftLLong(result, result, LSB);
9685     }
9686     /* 3 <= shCount <= 7, optimize */
9687     else{
9688         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9689         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9690         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9691     }
9692 }
9693
9694 /*-----------------------------------------------------------------*/
9695 /* genLeftShiftLiteral - left shifting by known count              */
9696 /*-----------------------------------------------------------------*/
9697 void pic16_genLeftShiftLiteral (operand *left,
9698                                  operand *right,
9699                                  operand *result,
9700                                  iCode *ic)
9701 {    
9702     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9703     int size;
9704
9705     FENTRY;
9706     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9707     pic16_freeAsmop(right,NULL,ic,TRUE);
9708
9709     pic16_aopOp(left,ic,FALSE);
9710     pic16_aopOp(result,ic,FALSE);
9711
9712     size = getSize(operandType(result));
9713
9714 #if VIEW_SIZE
9715     pic16_emitcode("; shift left ","result %d, left %d",size,
9716              AOP_SIZE(left));
9717 #endif
9718
9719     /* I suppose that the left size >= result size */
9720     if(shCount == 0){
9721         while(size--){
9722             movLeft2Result(left, size, result, size);
9723         }
9724     }
9725
9726     else if(shCount >= (size * 8))
9727         while(size--)
9728             pic16_aopPut(AOP(result),zero,size);
9729     else{
9730         switch (size) {
9731             case 1:
9732                 genlshOne (result,left,shCount);
9733                 break;
9734
9735             case 2:
9736             case 3:
9737                 genlshTwo (result,left,shCount);
9738                 break;
9739
9740             case 4:
9741                 genlshFour (result,left,shCount);
9742                 break;
9743         }
9744     }
9745     pic16_freeAsmop(left,NULL,ic,TRUE);
9746     pic16_freeAsmop(result,NULL,ic,TRUE);
9747 }
9748
9749 /*-----------------------------------------------------------------*
9750  * genMultiAsm - repeat assembly instruction for size of register.
9751  * if endian == 1, then the high byte (i.e base address + size of 
9752  * register) is used first else the low byte is used first;
9753  *-----------------------------------------------------------------*/
9754 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9755 {
9756
9757   int offset = 0;
9758
9759   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9760
9761   if(!reg)
9762     return;
9763
9764   if(!endian) {
9765     endian = 1;
9766   } else {
9767     endian = -1;
9768     offset = size-1;
9769   }
9770
9771   while(size--) {
9772     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9773     offset += endian;
9774   }
9775
9776 }
9777
9778 #if !(USE_GENERIC_SIGNED_SHIFT)
9779 /*-----------------------------------------------------------------*/
9780 /* genLeftShift - generates code for left shifting                 */
9781 /*-----------------------------------------------------------------*/
9782 static void genLeftShift (iCode *ic)
9783 {
9784   operand *left,*right, *result;
9785   int size, offset;
9786 //  char *l;
9787   symbol *tlbl , *tlbl1;
9788   pCodeOp *pctemp;
9789
9790   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9791
9792   right = IC_RIGHT(ic);
9793   left  = IC_LEFT(ic);
9794   result = IC_RESULT(ic);
9795
9796   pic16_aopOp(right,ic,FALSE);
9797
9798   /* if the shift count is known then do it 
9799      as efficiently as possible */
9800   if (AOP_TYPE(right) == AOP_LIT) {
9801     pic16_genLeftShiftLiteral (left,right,result,ic);
9802     return ;
9803   }
9804
9805   /* shift count is unknown then we have to form
9806    * a loop. Get the loop count in WREG : Note: we take
9807    * only the lower order byte since shifting
9808    * more than 32 bits make no sense anyway, ( the
9809    * largest size of an object can be only 32 bits ) */
9810   
9811   pic16_aopOp(left,ic,FALSE);
9812   pic16_aopOp(result,ic,FALSE);
9813
9814   /* now move the left to the result if they are not the
9815    * same, and if size > 1,
9816    * and if right is not same to result (!!!) -- VR */
9817   if (!pic16_sameRegs(AOP(left),AOP(result))
9818       && (AOP_SIZE(result) > 1)) {
9819
9820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9821
9822     size = AOP_SIZE(result);
9823     offset=0;
9824     while (size--) {
9825
9826 #if 0
9827       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9828       if (*l == '@' && (IS_AOP_PREG(result))) {
9829
9830           pic16_emitcode("mov","a,%s",l);
9831           pic16_aopPut(AOP(result),"a",offset);
9832       } else
9833 #endif
9834       {
9835         /* we don't know if left is a literal or a register, take care -- VR */
9836         mov2f(AOP(result), AOP(left), offset);
9837       }
9838       offset++;
9839     }
9840   }
9841
9842   size = AOP_SIZE(result);
9843
9844   /* if it is only one byte then */
9845   if (size == 1) {
9846     if(optimized_for_speed) {
9847       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9848       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9849       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9850       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9851       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9852       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9853       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9854       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9855       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9856       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9857       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9858       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9859     } else {
9860
9861       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9862
9863       tlbl = newiTempLabel(NULL);
9864
9865 #if 1
9866       /* this is already done, why change it? */
9867       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9868                 mov2f(AOP(result), AOP(left), 0);
9869       }
9870 #endif
9871
9872       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9873       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9874       pic16_emitpLabel(tlbl->key);
9875       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9876       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9877       emitSKPC;
9878       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9879     }
9880     goto release ;
9881   }
9882     
9883   if (pic16_sameRegs(AOP(left),AOP(result))) {
9884
9885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9886     
9887     tlbl = newiTempLabel(NULL);
9888     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9889     genMultiAsm(POC_RRCF, result, size,1);
9890     pic16_emitpLabel(tlbl->key);
9891     genMultiAsm(POC_RLCF, result, size,0);
9892     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9893     emitSKPC;
9894     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9895     goto release;
9896   }
9897
9898   //tlbl = newiTempLabel(NULL);
9899   //offset = 0 ;   
9900   //tlbl1 = newiTempLabel(NULL);
9901
9902   //reAdjustPreg(AOP(result));    
9903     
9904   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9905   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9906   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9907   //MOVA(l);
9908   //pic16_emitcode("add","a,acc");         
9909   //pic16_aopPut(AOP(result),"a",offset++);
9910   //while (--size) {
9911   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9912   //  MOVA(l);
9913   //  pic16_emitcode("rlc","a");         
9914   //  pic16_aopPut(AOP(result),"a",offset++);
9915   //}
9916   //reAdjustPreg(AOP(result));
9917
9918   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9919   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9920
9921
9922   tlbl = newiTempLabel(NULL);
9923   tlbl1= newiTempLabel(NULL);
9924
9925   size = AOP_SIZE(result);
9926   offset = 1;
9927
9928   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9929
9930   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9931
9932   /* offset should be 0, 1 or 3 */
9933   
9934   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9935   emitSKPNZ;
9936   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9937
9938   pic16_emitpcode(POC_MOVWF, pctemp);
9939
9940
9941   pic16_emitpLabel(tlbl->key);
9942
9943   emitCLRC;
9944   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9945   while(--size)
9946     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9947
9948   pic16_emitpcode(POC_DECFSZ,  pctemp);
9949   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9950   pic16_emitpLabel(tlbl1->key);
9951
9952   pic16_popReleaseTempReg(pctemp,1);
9953
9954
9955  release:
9956   pic16_freeAsmop (right,NULL,ic,TRUE);
9957   pic16_freeAsmop(left,NULL,ic,TRUE);
9958   pic16_freeAsmop(result,NULL,ic,TRUE);
9959 }
9960 #endif
9961
9962
9963 #if 0
9964 #error old code (left here for reference)
9965 /*-----------------------------------------------------------------*/
9966 /* genLeftShift - generates code for left shifting                 */
9967 /*-----------------------------------------------------------------*/
9968 static void genLeftShift (iCode *ic)
9969 {
9970   operand *left,*right, *result;
9971   int size, offset;
9972   char *l;
9973   symbol *tlbl , *tlbl1;
9974   pCodeOp *pctemp;
9975
9976   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9977
9978   right = IC_RIGHT(ic);
9979   left  = IC_LEFT(ic);
9980   result = IC_RESULT(ic);
9981
9982   pic16_aopOp(right,ic,FALSE);
9983
9984   /* if the shift count is known then do it 
9985      as efficiently as possible */
9986   if (AOP_TYPE(right) == AOP_LIT) {
9987     pic16_genLeftShiftLiteral (left,right,result,ic);
9988     return ;
9989   }
9990
9991   /* shift count is unknown then we have to form 
9992      a loop get the loop count in B : Note: we take
9993      only the lower order byte since shifting
9994      more that 32 bits make no sense anyway, ( the
9995      largest size of an object can be only 32 bits ) */  
9996
9997     
9998   pic16_aopOp(left,ic,FALSE);
9999   pic16_aopOp(result,ic,FALSE);
10000
10001   /* now move the left to the result if they are not the
10002      same */
10003   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10004       AOP_SIZE(result) > 1) {
10005
10006     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10007
10008     size = AOP_SIZE(result);
10009     offset=0;
10010     while (size--) {
10011       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10012       if (*l == '@' && (IS_AOP_PREG(result))) {
10013
10014         pic16_emitcode("mov","a,%s",l);
10015         pic16_aopPut(AOP(result),"a",offset);
10016       } else {
10017
10018         /* we don't know if left is a literal or a register, take care -- VR */
10019         mov2f(AOP(result), AOP(left), offset);
10020       }
10021       offset++;
10022     }
10023   }
10024
10025   size = AOP_SIZE(result);
10026
10027   /* if it is only one byte then */
10028   if (size == 1) {
10029     if(optimized_for_speed) {
10030       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10031       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10032       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10033       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10034       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10035       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10036       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10037       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10038       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10039       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10040       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10041       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10042     } else {
10043
10044       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10045
10046       tlbl = newiTempLabel(NULL);
10047       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10048                 mov2f(AOP(result), AOP(left), 0);
10049                 
10050 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10051 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10052       }
10053
10054       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10055       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10056       pic16_emitpLabel(tlbl->key);
10057       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10058       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10059       emitSKPC;
10060       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10061     }
10062     goto release ;
10063   }
10064     
10065   if (pic16_sameRegs(AOP(left),AOP(result))) {
10066
10067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10068     
10069     tlbl = newiTempLabel(NULL);
10070     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10071     genMultiAsm(POC_RRCF, result, size,1);
10072     pic16_emitpLabel(tlbl->key);
10073     genMultiAsm(POC_RLCF, result, size,0);
10074     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10075     emitSKPC;
10076     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10077     goto release;
10078   }
10079
10080   //tlbl = newiTempLabel(NULL);
10081   //offset = 0 ;   
10082   //tlbl1 = newiTempLabel(NULL);
10083
10084   //reAdjustPreg(AOP(result));    
10085     
10086   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10087   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10088   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10089   //MOVA(l);
10090   //pic16_emitcode("add","a,acc");         
10091   //pic16_aopPut(AOP(result),"a",offset++);
10092   //while (--size) {
10093   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10094   //  MOVA(l);
10095   //  pic16_emitcode("rlc","a");         
10096   //  pic16_aopPut(AOP(result),"a",offset++);
10097   //}
10098   //reAdjustPreg(AOP(result));
10099
10100   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10101   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10102
10103
10104   tlbl = newiTempLabel(NULL);
10105   tlbl1= newiTempLabel(NULL);
10106
10107   size = AOP_SIZE(result);
10108   offset = 1;
10109
10110   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10111
10112   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10113
10114   /* offset should be 0, 1 or 3 */
10115   
10116   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10117   emitSKPNZ;
10118   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10119
10120   pic16_emitpcode(POC_MOVWF, pctemp);
10121
10122
10123   pic16_emitpLabel(tlbl->key);
10124
10125   emitCLRC;
10126   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10127   while(--size)
10128     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10129
10130   pic16_emitpcode(POC_DECFSZ,  pctemp);
10131   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10132   pic16_emitpLabel(tlbl1->key);
10133
10134   pic16_popReleaseTempReg(pctemp,1);
10135
10136
10137  release:
10138   pic16_freeAsmop (right,NULL,ic,TRUE);
10139   pic16_freeAsmop(left,NULL,ic,TRUE);
10140   pic16_freeAsmop(result,NULL,ic,TRUE);
10141 }
10142 #endif
10143
10144 /*-----------------------------------------------------------------*/
10145 /* genrshOne - right shift a one byte quantity by known count      */
10146 /*-----------------------------------------------------------------*/
10147 static void genrshOne (operand *result, operand *left,
10148                        int shCount, int sign)
10149 {
10150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10151     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10152 }
10153
10154 /*-----------------------------------------------------------------*/
10155 /* genrshTwo - right shift two bytes by known amount != 0          */
10156 /*-----------------------------------------------------------------*/
10157 static void genrshTwo (operand *result,operand *left,
10158                        int shCount, int sign)
10159 {
10160   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10161   /* if shCount >= 8 */
10162   if (shCount >= 8) {
10163     shCount -= 8 ;
10164     if (shCount)
10165       shiftR1Left2Result(left, MSB16, result, LSB,
10166                          shCount, sign);
10167     else
10168       movLeft2Result(left, MSB16, result, LSB);
10169
10170     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10171
10172     if(sign) {
10173       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10174       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10175     }
10176   }
10177
10178   /*  1 <= shCount <= 7 */
10179   else
10180     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10181 }
10182
10183 /*-----------------------------------------------------------------*/
10184 /* shiftRLong - shift right one long from left to result           */
10185 /* offl = LSB or MSB16                                             */
10186 /*-----------------------------------------------------------------*/
10187 static void shiftRLong (operand *left, int offl,
10188                         operand *result, int sign)
10189 {
10190     int size = AOP_SIZE(result);
10191     int same = pic16_sameRegs(AOP(left),AOP(result));
10192     int i;
10193     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10194
10195         if (same && (offl == MSB16)) { //shift one byte right
10196                 for(i=MSB16;i<size;i++) {
10197                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10198                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10199                 }
10200         }
10201
10202     if(sign)
10203                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10204         else
10205                 emitCLRC;
10206
10207         if (same) {
10208                 if (offl == LSB)
10209                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10210         } else {
10211         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10212         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10213         }
10214
10215     if(offl == MSB16) {
10216         /* add sign of "a" */
10217         pic16_addSign(result, MSB32, sign);
10218         }
10219
10220         if (same) {
10221         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10222         } else {
10223         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10224         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10225         }
10226         
10227         if (same) {
10228         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10229         } else {
10230         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10231         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10232         }
10233
10234         if (same) {
10235         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10236         } else {
10237         if(offl == LSB){
10238                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10239                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10240         }
10241         }
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genrshFour - shift four byte by a known amount != 0             */
10246 /*-----------------------------------------------------------------*/
10247 static void genrshFour (operand *result, operand *left,
10248                         int shCount, int sign)
10249 {
10250   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10251   /* if shifting more that 3 bytes */
10252   if(shCount >= 24 ) {
10253     shCount -= 24;
10254     if(shCount)
10255       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10256     else
10257       movLeft2Result(left, MSB32, result, LSB);
10258
10259     pic16_addSign(result, MSB16, sign);
10260   }
10261   else if(shCount >= 16){
10262     shCount -= 16;
10263     if(shCount)
10264       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10265     else{
10266       movLeft2Result(left, MSB24, result, LSB);
10267       movLeft2Result(left, MSB32, result, MSB16);
10268     }
10269     pic16_addSign(result, MSB24, sign);
10270   }
10271   else if(shCount >= 8){
10272     shCount -= 8;
10273     if(shCount == 1)
10274       shiftRLong(left, MSB16, result, sign);
10275     else if(shCount == 0){
10276       movLeft2Result(left, MSB16, result, LSB);
10277       movLeft2Result(left, MSB24, result, MSB16);
10278       movLeft2Result(left, MSB32, result, MSB24);
10279       pic16_addSign(result, MSB32, sign);
10280     }
10281     else{ //shcount >= 2
10282       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10283       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10284       /* the last shift is signed */
10285       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10286       pic16_addSign(result, MSB32, sign);
10287     }
10288   }
10289   else{   /* 1 <= shCount <= 7 */
10290     if(shCount <= 2){
10291       shiftRLong(left, LSB, result, sign);
10292       if(shCount == 2)
10293         shiftRLong(result, LSB, result, sign);
10294     }
10295     else{
10296       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10297       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10298       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10299     }
10300   }
10301 }
10302
10303 /*-----------------------------------------------------------------*/
10304 /* genRightShiftLiteral - right shifting by known count            */
10305 /*-----------------------------------------------------------------*/
10306 static void genRightShiftLiteral (operand *left,
10307                                   operand *right,
10308                                   operand *result,
10309                                   iCode *ic,
10310                                   int sign)
10311 {    
10312   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10313   int lsize,res_size;
10314
10315   pic16_freeAsmop(right,NULL,ic,TRUE);
10316
10317   pic16_aopOp(left,ic,FALSE);
10318   pic16_aopOp(result,ic,FALSE);
10319
10320   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10321
10322 #if VIEW_SIZE
10323   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10324                  AOP_SIZE(left));
10325 #endif
10326
10327   lsize = pic16_getDataSize(left);
10328   res_size = pic16_getDataSize(result);
10329   /* test the LEFT size !!! */
10330
10331   /* I suppose that the left size >= result size */
10332   if(shCount == 0){
10333     while(res_size--)
10334       movLeft2Result(left, lsize, result, res_size);
10335   }
10336
10337   else if(shCount >= (lsize * 8)){
10338
10339     if(res_size == 1) {
10340       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10341       if(sign) {
10342         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10343         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10344       }
10345     } else {
10346
10347       if(sign) {
10348         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10349         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10350         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10351         while(res_size--)
10352           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10353
10354       } else {
10355
10356         while(res_size--)
10357           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10358       }
10359     }
10360   } else {
10361
10362     switch (res_size) {
10363     case 1:
10364       genrshOne (result,left,shCount,sign);
10365       break;
10366
10367     case 2:
10368       genrshTwo (result,left,shCount,sign);
10369       break;
10370
10371     case 4:
10372       genrshFour (result,left,shCount,sign);
10373       break;
10374     default :
10375       break;
10376     }
10377
10378   }
10379
10380   pic16_freeAsmop(left,NULL,ic,TRUE);
10381   pic16_freeAsmop(result,NULL,ic,TRUE);
10382 }
10383
10384 #if !(USE_GENERIC_SIGNED_SHIFT)
10385 /*-----------------------------------------------------------------*/
10386 /* genSignedRightShift - right shift of signed number              */
10387 /*-----------------------------------------------------------------*/
10388 static void genSignedRightShift (iCode *ic)
10389 {
10390   operand *right, *left, *result;
10391   int size, offset;
10392   //  char *l;
10393   symbol *tlbl, *tlbl1 ;
10394   pCodeOp *pctemp;
10395
10396   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10397
10398   /* we do it the hard way put the shift count in b
10399      and loop thru preserving the sign */
10400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10401
10402   right = IC_RIGHT(ic);
10403   left  = IC_LEFT(ic);
10404   result = IC_RESULT(ic);
10405
10406   pic16_aopOp(right,ic,FALSE);  
10407   pic16_aopOp(left,ic,FALSE);
10408   pic16_aopOp(result,ic,FALSE);
10409
10410
10411   if ( AOP_TYPE(right) == AOP_LIT) {
10412     genRightShiftLiteral (left,right,result,ic,1);
10413     return ;
10414   }
10415   /* shift count is unknown then we have to form 
10416      a loop get the loop count in B : Note: we take
10417      only the lower order byte since shifting
10418      more that 32 bits make no sense anyway, ( the
10419      largest size of an object can be only 32 bits ) */  
10420
10421   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10422   //pic16_emitcode("inc","b");
10423   //pic16_freeAsmop (right,NULL,ic,TRUE);
10424   //pic16_aopOp(left,ic,FALSE);
10425   //pic16_aopOp(result,ic,FALSE);
10426
10427   /* now move the left to the result if they are not the
10428      same */
10429   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10430       AOP_SIZE(result) > 1) {
10431
10432     size = AOP_SIZE(result);
10433     offset=0;
10434     while (size--) { 
10435       /*
10436         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10437         if (*l == '@' && IS_AOP_PREG(result)) {
10438
10439         pic16_emitcode("mov","a,%s",l);
10440         pic16_aopPut(AOP(result),"a",offset);
10441         } else
10442         pic16_aopPut(AOP(result),l,offset);
10443       */
10444       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10445       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10446
10447       offset++;
10448     }
10449   }
10450
10451   /* mov the highest order bit to OVR */    
10452   tlbl = newiTempLabel(NULL);
10453   tlbl1= newiTempLabel(NULL);
10454
10455   size = AOP_SIZE(result);
10456   offset = size - 1;
10457
10458   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10459
10460   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10461
10462   /* offset should be 0, 1 or 3 */
10463   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10464   emitSKPNZ;
10465   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10466
10467   pic16_emitpcode(POC_MOVWF, pctemp);
10468
10469
10470   pic16_emitpLabel(tlbl->key);
10471
10472   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10473   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10474
10475   while(--size) {
10476     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10477   }
10478
10479   pic16_emitpcode(POC_DECFSZ,  pctemp);
10480   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10481   pic16_emitpLabel(tlbl1->key);
10482
10483   pic16_popReleaseTempReg(pctemp,1);
10484 #if 0
10485   size = AOP_SIZE(result);
10486   offset = size - 1;
10487   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10488   pic16_emitcode("rlc","a");
10489   pic16_emitcode("mov","ov,c");
10490   /* if it is only one byte then */
10491   if (size == 1) {
10492     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10493     MOVA(l);
10494     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10495     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10496     pic16_emitcode("mov","c,ov");
10497     pic16_emitcode("rrc","a");
10498     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10499     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10500     pic16_aopPut(AOP(result),"a",0);
10501     goto release ;
10502   }
10503
10504   reAdjustPreg(AOP(result));
10505   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10506   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10507   pic16_emitcode("mov","c,ov");
10508   while (size--) {
10509     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10510     MOVA(l);
10511     pic16_emitcode("rrc","a");         
10512     pic16_aopPut(AOP(result),"a",offset--);
10513   }
10514   reAdjustPreg(AOP(result));
10515   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10516   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10517
10518  release:
10519 #endif
10520
10521   pic16_freeAsmop(left,NULL,ic,TRUE);
10522   pic16_freeAsmop(result,NULL,ic,TRUE);
10523   pic16_freeAsmop(right,NULL,ic,TRUE);
10524 }
10525 #endif
10526
10527 #if !(USE_GENERIC_SIGNED_SHIFT)
10528 #warning This implementation of genRightShift() is incomplete!
10529 /*-----------------------------------------------------------------*/
10530 /* genRightShift - generate code for right shifting                */
10531 /*-----------------------------------------------------------------*/
10532 static void genRightShift (iCode *ic)
10533 {
10534     operand *right, *left, *result;
10535     sym_link *letype ;
10536     int size, offset;
10537     char *l;
10538     symbol *tlbl, *tlbl1 ;
10539
10540     /* if signed then we do it the hard way preserve the
10541     sign bit moving it inwards */
10542     letype = getSpec(operandType(IC_LEFT(ic)));
10543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10544
10545     if (!SPEC_USIGN(letype)) {
10546         genSignedRightShift (ic);
10547         return ;
10548     }
10549
10550     /* signed & unsigned types are treated the same : i.e. the
10551     signed is NOT propagated inwards : quoting from the
10552     ANSI - standard : "for E1 >> E2, is equivalent to division
10553     by 2**E2 if unsigned or if it has a non-negative value,
10554     otherwise the result is implementation defined ", MY definition
10555     is that the sign does not get propagated */
10556
10557     right = IC_RIGHT(ic);
10558     left  = IC_LEFT(ic);
10559     result = IC_RESULT(ic);
10560
10561     pic16_aopOp(right,ic,FALSE);
10562
10563     /* if the shift count is known then do it 
10564     as efficiently as possible */
10565     if (AOP_TYPE(right) == AOP_LIT) {
10566         genRightShiftLiteral (left,right,result,ic, 0);
10567         return ;
10568     }
10569
10570     /* shift count is unknown then we have to form 
10571     a loop get the loop count in B : Note: we take
10572     only the lower order byte since shifting
10573     more that 32 bits make no sense anyway, ( the
10574     largest size of an object can be only 32 bits ) */  
10575
10576     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10577     pic16_emitcode("inc","b");
10578     pic16_aopOp(left,ic,FALSE);
10579     pic16_aopOp(result,ic,FALSE);
10580
10581     /* now move the left to the result if they are not the
10582     same */
10583     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10584         AOP_SIZE(result) > 1) {
10585
10586         size = AOP_SIZE(result);
10587         offset=0;
10588         while (size--) {
10589             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10590             if (*l == '@' && IS_AOP_PREG(result)) {
10591
10592                 pic16_emitcode("mov","a,%s",l);
10593                 pic16_aopPut(AOP(result),"a",offset);
10594             } else
10595                 pic16_aopPut(AOP(result),l,offset);
10596             offset++;
10597         }
10598     }
10599
10600     tlbl = newiTempLabel(NULL);
10601     tlbl1= newiTempLabel(NULL);
10602     size = AOP_SIZE(result);
10603     offset = size - 1;
10604
10605     /* if it is only one byte then */
10606     if (size == 1) {
10607
10608       tlbl = newiTempLabel(NULL);
10609       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10610         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10611         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10612       }
10613
10614       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10615       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10616       pic16_emitpLabel(tlbl->key);
10617       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10618       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10619       emitSKPC;
10620       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10621
10622       goto release ;
10623     }
10624
10625     reAdjustPreg(AOP(result));
10626     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10627     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10628     CLRC;
10629     while (size--) {
10630         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10631         MOVA(l);
10632         pic16_emitcode("rrc","a");         
10633         pic16_aopPut(AOP(result),"a",offset--);
10634     }
10635     reAdjustPreg(AOP(result));
10636
10637     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10638     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10639
10640 release:
10641     pic16_freeAsmop(left,NULL,ic,TRUE);
10642     pic16_freeAsmop (right,NULL,ic,TRUE);
10643     pic16_freeAsmop(result,NULL,ic,TRUE);
10644 }
10645 #endif
10646
10647 #if (USE_GENERIC_SIGNED_SHIFT)
10648 /*-----------------------------------------------------------------*/
10649 /* genGenericShift - generates code for left or right shifting     */
10650 /*-----------------------------------------------------------------*/
10651 static void genGenericShift (iCode *ic, int isShiftLeft) {
10652   operand *left,*right, *result;
10653   int offset;
10654   int sign, signedCount;
10655   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10656   PIC_OPCODE pos_shift, neg_shift;
10657
10658   FENTRY;
10659
10660   right = IC_RIGHT(ic);
10661   left  = IC_LEFT(ic);
10662   result = IC_RESULT(ic);
10663
10664   pic16_aopOp(right,ic,FALSE);
10665   pic16_aopOp(left,ic,FALSE);
10666   pic16_aopOp(result,ic,FALSE);
10667
10668   sign = !SPEC_USIGN(operandType (left));
10669   signedCount = !SPEC_USIGN(operandType (right));
10670
10671   /* if the shift count is known then do it 
10672      as efficiently as possible */
10673   if (AOP_TYPE(right) == AOP_LIT) {
10674     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10675     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10676     // we should modify right->aopu.aop_lit here!
10677     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10678     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10679     if (isShiftLeft)
10680       pic16_genLeftShiftLiteral (left,right,result,ic);
10681     else
10682       genRightShiftLiteral (left,right,result,ic, sign);
10683
10684     goto release;
10685   } // if (right is literal)
10686
10687   /* shift count is unknown then we have to form a loop.
10688    * Note: we take only the lower order byte since shifting
10689    * more than 32 bits make no sense anyway, ( the
10690    * largest size of an object can be only 32 bits )
10691    * Note: we perform arithmetic shifts if the left operand is
10692    * signed and we do an (effective) right shift, i. e. we
10693    * shift in the sign bit from the left. */
10694    
10695   label_complete = newiTempLabel ( NULL );
10696   label_loop_pos = newiTempLabel ( NULL );
10697   label_loop_neg = NULL;
10698   label_negative = NULL;
10699   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10700   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10701
10702   if (signedCount) {
10703     // additional labels needed
10704     label_loop_neg = newiTempLabel ( NULL );
10705     label_negative = newiTempLabel ( NULL );
10706   } // if
10707
10708   // copy source to result -- this will effectively truncate the left operand to the size of result!
10709   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10710   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10711   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10712     mov2f (AOP(result),AOP(left), offset);
10713   } // for
10714
10715   // if result is longer than left, fill with zeros (or sign)
10716   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10717     if (sign && AOP_SIZE(left) > 0) {
10718       // shift signed operand -- fill with sign
10719       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10720       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10721       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10722       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10723         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10724       } // for
10725     } else {
10726       // shift unsigned operand -- fill result with zeros
10727       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10728         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10729       } // for
10730     }
10731   } // if (size mismatch)
10732
10733   pic16_mov2w (AOP(right), 0);
10734   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10735   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10736   
10737 #if 0
10738   // perform a shift by one (shift count is positive)
10739   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10740   // 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])
10741   pic16_emitpLabel (label_loop_pos->key);
10742   emitCLRC;
10743   if (sign && (pos_shift == POC_RRCF)) {
10744     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10745     emitSETC;
10746   } // if
10747   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10748   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10749   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10750 #else
10751   // perform a shift by one (shift count is positive)
10752   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10753   // 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])
10754   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10755   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10756   emitCLRC;
10757   pic16_emitpLabel (label_loop_pos->key);
10758   if (sign && (pos_shift == POC_RRCF)) {
10759     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10760     emitSETC;
10761   } // if
10762   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10763   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10764   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10765   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10766 #endif
10767
10768   if (signedCount) {
10769     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10770
10771     pic16_emitpLabel (label_negative->key);
10772     // perform a shift by -1 (shift count is negative)
10773     // 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)
10774     emitCLRC;
10775     pic16_emitpLabel (label_loop_neg->key);
10776     if (sign && (neg_shift == POC_RRCF)) {
10777       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10778       emitSETC;
10779     } // if
10780     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10781     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10782     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10783     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10784   } // if (signedCount)
10785
10786   pic16_emitpLabel (label_complete->key);
10787
10788 release:
10789   pic16_freeAsmop (right,NULL,ic,TRUE);
10790   pic16_freeAsmop(left,NULL,ic,TRUE);
10791   pic16_freeAsmop(result,NULL,ic,TRUE);
10792 }
10793
10794 static void genLeftShift (iCode *ic) {
10795   genGenericShift (ic, 1);
10796 }
10797
10798 static void genRightShift (iCode *ic) {
10799   genGenericShift (ic, 0);
10800 }
10801 #endif
10802
10803
10804 void pic16_loadFSR0(operand *op)
10805 {
10806         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10807 }
10808
10809 /*-----------------------------------------------------------------*/
10810 /* genUnpackBits - generates code for unpacking bits               */
10811 /*-----------------------------------------------------------------*/
10812 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10813 {    
10814   int shCnt ;
10815   int rlen = 0 ;
10816   sym_link *etype, *letype;
10817   int blen=0, bstr=0;
10818   int lbstr;
10819   int offset = 0 ;
10820
10821     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10822     etype = getSpec(operandType(result));
10823     letype = getSpec(operandType(left));
10824     
10825 //    if(IS_BITFIELD(etype)) {
10826       blen = SPEC_BLEN(etype);
10827       bstr = SPEC_BSTR(etype);
10828 //    }
10829
10830     lbstr = SPEC_BSTR( letype );
10831
10832 #if 1
10833     if((blen == 1) && (bstr < 8)) {
10834       /* it is a single bit, so use the appropriate bit instructions */
10835       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10836
10837       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10838       
10839       if((ptype == POINTER) && (result)) {
10840         /* workaround to reduce the extra lfsr instruction */
10841         pic16_emitpcode(POC_BTFSC,
10842               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10843       } else {
10844         pic16_emitpcode(POC_BTFSC,
10845               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10846       }
10847         
10848       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10849
10850       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10851       return;
10852     }
10853
10854 #endif
10855
10856         /* the following call to pic16_loadFSR0 is temporary until
10857          * optimization to handle single bit assignments is added
10858          * to the function. Until then use the old safe way! -- VR */
10859         pic16_loadFSR0( left );
10860  
10861         /* read the first byte  */
10862         switch (ptype) {
10863                 case POINTER:
10864                 case IPOINTER:
10865                 case PPOINTER:
10866                 case FPOINTER:
10867                 case GPOINTER:
10868                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10869                         break;
10870                 case CPOINTER:
10871                         pic16_emitcode("clr","a");
10872                         pic16_emitcode("movc","a","@a+dptr");
10873                         break;
10874         }
10875         
10876
10877         /* if we have bitdisplacement then it fits   */
10878         /* into this byte completely or if length is */
10879         /* less than a byte                          */
10880         if ((shCnt = SPEC_BSTR(etype)) || 
10881                 (SPEC_BLEN(etype) <= 8))  {
10882
10883                 /* shift right acc */
10884                 AccRsh(shCnt, 0);
10885
10886                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10887                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10888
10889 /* VR -- normally I would use the following, but since we use the hack,
10890  * to avoid the masking from AccRsh, why not mask it right now? */
10891
10892 /*
10893                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10894 */
10895
10896                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10897           return ;
10898         }
10899
10900
10901
10902         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10903         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10904         exit(-1);
10905
10906     /* bit field did not fit in a byte  */
10907     rlen = SPEC_BLEN(etype) - 8;
10908     pic16_aopPut(AOP(result),"a",offset++);
10909
10910     while (1)  {
10911
10912         switch (ptype) {
10913         case POINTER:
10914         case IPOINTER:
10915             pic16_emitcode("inc","%s",rname);
10916             pic16_emitcode("mov","a,@%s",rname);
10917             break;
10918             
10919         case PPOINTER:
10920             pic16_emitcode("inc","%s",rname);
10921             pic16_emitcode("movx","a,@%s",rname);
10922             break;
10923
10924         case FPOINTER:
10925             pic16_emitcode("inc","dptr");
10926             pic16_emitcode("movx","a,@dptr");
10927             break;
10928             
10929         case CPOINTER:
10930             pic16_emitcode("clr","a");
10931             pic16_emitcode("inc","dptr");
10932             pic16_emitcode("movc","a","@a+dptr");
10933             break;
10934             
10935         case GPOINTER:
10936             pic16_emitcode("inc","dptr");
10937             pic16_emitcode("lcall","__gptrget");
10938             break;
10939         }
10940
10941         rlen -= 8;            
10942         /* if we are done */
10943         if ( rlen <= 0 )
10944             break ;
10945         
10946         pic16_aopPut(AOP(result),"a",offset++);
10947                               
10948     }
10949     
10950     if (rlen) {
10951         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10952         pic16_aopPut(AOP(result),"a",offset);          
10953     }
10954     
10955     return ;
10956 }
10957
10958
10959 static void genDataPointerGet(operand *left,
10960                               operand *result,
10961                               iCode *ic)
10962 {
10963   int size, offset = 0, leoffset=0 ;
10964
10965         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10966         pic16_aopOp(result, ic, FALSE);
10967
10968         size = AOP_SIZE(result);
10969 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10970
10971
10972 #if 0
10973         /* The following tests may save a redudant movff instruction when
10974          * accessing unions */
10975          
10976         /* if they are the same */
10977         if (operandsEqu (left, result)) {
10978                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10979                 goto release;
10980         }
10981 #endif
10982
10983 #if 0
10984         /* if they are the same registers */
10985         if (pic16_sameRegs(AOP(left),AOP(result))) {
10986                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10987                 goto release;
10988         }
10989 #endif
10990
10991 #if 1
10992         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10993                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10994                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10995                 goto release;
10996         }
10997 #endif
10998
10999
11000 #if 0
11001         if ( AOP_TYPE(left) == AOP_PCODE) {
11002                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11003                                 AOP(left)->aopu.pcop->name,
11004                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11005                                 PCOR(AOP(left)->aopu.pcop)->instance:
11006                                 PCOI(AOP(left)->aopu.pcop)->offset);
11007         }
11008 #endif
11009
11010         if(AOP(left)->aopu.pcop->type == PO_DIR)
11011                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11012
11013         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11014
11015         while (size--) {
11016                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11017                 
11018                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11019                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11020                         pic16_mov2w(AOP(left), offset); // patch 8
11021                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11022                 } else {
11023                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11024                                 pic16_popGet(AOP(left), offset), //patch 8
11025                                 pic16_popGet(AOP(result), offset)));
11026                 }
11027
11028                 offset++;
11029                 leoffset++;
11030         }
11031
11032 release:
11033     pic16_freeAsmop(result,NULL,ic,TRUE);
11034 }
11035
11036
11037
11038 /*-----------------------------------------------------------------*/
11039 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11040 /*-----------------------------------------------------------------*/
11041 static void genNearPointerGet (operand *left, 
11042                                operand *result, 
11043                                iCode *ic)
11044 {
11045   asmop *aop = NULL;
11046   //regs *preg = NULL ;
11047   sym_link *rtype, *retype;
11048   sym_link *ltype = operandType(left);    
11049
11050     FENTRY;
11051     
11052     rtype = operandType(result);
11053     retype= getSpec(rtype);
11054     
11055     pic16_aopOp(left,ic,FALSE);
11056
11057 //    pic16_DumpOp("(left)",left);
11058 //    pic16_DumpOp("(result)",result);
11059
11060     /* if left is rematerialisable and
11061      * result is not bit variable type and
11062      * the left is pointer to data space i.e
11063      * lower 128 bytes of space */
11064     
11065     if (AOP_TYPE(left) == AOP_PCODE
11066       && !IS_BITFIELD(retype)
11067       && DCL_TYPE(ltype) == POINTER) {
11068
11069         genDataPointerGet (left,result,ic);
11070         pic16_freeAsmop(left, NULL, ic, TRUE);
11071         return ;
11072     }
11073     
11074     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11075     pic16_aopOp (result,ic,FALSE);
11076     
11077     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11078
11079 #if 1
11080     if(IS_BITFIELD( retype )
11081       && (SPEC_BLEN(operandType(result))==1)
11082     ) {
11083       iCode *nextic;
11084       pCodeOp *jop;
11085       int bitstrt, bytestrt;
11086
11087         /* if this is bitfield of size 1, see if we are checking the value
11088          * of a single bit in an if-statement,
11089          * if yes, then don't generate usual code, but execute the
11090          * genIfx directly -- VR */
11091
11092         nextic = ic->next;
11093
11094         /* CHECK: if next iCode is IFX
11095          * and current result operand is nextic's conditional operand
11096          * and current result operand live ranges ends at nextic's key number
11097          */
11098         if((nextic->op == IFX)
11099           && (result == IC_COND(nextic))
11100           && (OP_LIVETO(result) == nextic->seq)
11101           ) {
11102             /* everything is ok then */
11103             /* find a way to optimize the genIfx iCode */
11104
11105             bytestrt = SPEC_BSTR(operandType(result))/8;
11106             bitstrt = SPEC_BSTR(operandType(result))%8;
11107             
11108             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11109
11110             genIfxpCOpJump(nextic, jop);
11111             
11112             pic16_freeAsmop(left, NULL, ic, TRUE);
11113             pic16_freeAsmop(result, NULL, ic, TRUE);
11114             return;
11115         }
11116     }
11117 #endif
11118
11119
11120     /* if the value is already in a pointer register
11121      * then don't need anything more */
11122     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11123       /* otherwise get a free pointer register */
11124       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11125                 
11126       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11127       /* bitfields will be handled by genUnpackBits */
11128       if(!IS_BITFIELD(retype)) {
11129
11130         if(is_LitAOp( AOP(left) )) {
11131           pic16_loadFSR0( left );
11132         } else {
11133             // set up FSR0 with address from left
11134             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11135             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11136         }
11137       }
11138     }
11139
11140     /* if bitfield then unpack the bits */
11141     if (IS_BITFIELD(retype)) 
11142       genUnpackBits (result, left, NULL, POINTER);
11143     else {
11144       /* we have can just get the values */
11145       int size = AOP_SIZE(result);
11146       int offset = 0;   
11147         
11148       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11149
11150       /* fsr0 is loaded already -- VR */
11151 //      pic16_loadFSR0( left );
11152
11153 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11154 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11155       while(size--) {
11156         if(size) {
11157           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11158                 pic16_popGet(AOP(result), offset++)));
11159         } else {
11160           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11161                 pic16_popGet(AOP(result), offset++)));
11162         }
11163       }
11164 #if 0
11165 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11166 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11167       if(size)
11168         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11169 #endif
11170 /*
11171         while (size--) {
11172             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11173
11174                 pic16_emitcode("mov","a,@%s",rname);
11175                 pic16_aopPut(AOP(result),"a",offset);
11176             } else {
11177                 sprintf(buffer,"@%s",rname);
11178                 pic16_aopPut(AOP(result),buffer,offset);
11179             }
11180             offset++ ;
11181             if (size)
11182                 pic16_emitcode("inc","%s",rname);
11183         }
11184 */
11185     }
11186
11187     /* now some housekeeping stuff */
11188     if (aop) {
11189       /* we had to allocate for this iCode */
11190       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11191       pic16_freeAsmop(NULL,aop,ic,TRUE);
11192     } else { 
11193       /* we did not allocate which means left
11194        * already in a pointer register, then
11195        * if size > 0 && this could be used again
11196        * we have to point it back to where it 
11197        * belongs */
11198       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11199       if (AOP_SIZE(result) > 1
11200         && !OP_SYMBOL(left)->remat
11201         && ( OP_SYMBOL(left)->liveTo > ic->seq
11202             || ic->depth )) {
11203 //        int size = AOP_SIZE(result) - 1;
11204 //        while (size--)
11205 //          pic16_emitcode("dec","%s",rname);
11206         }
11207     }
11208
11209     /* done */
11210     pic16_freeAsmop(left,NULL,ic,TRUE);
11211     pic16_freeAsmop(result,NULL,ic,TRUE);
11212 }
11213
11214 /*-----------------------------------------------------------------*/
11215 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11216 /*-----------------------------------------------------------------*/
11217 static void genPagedPointerGet (operand *left, 
11218                                operand *result, 
11219                                iCode *ic)
11220 {
11221     asmop *aop = NULL;
11222     regs *preg = NULL ;
11223     char *rname ;
11224     sym_link *rtype, *retype;    
11225
11226     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11227
11228     rtype = operandType(result);
11229     retype= getSpec(rtype);
11230     
11231     pic16_aopOp(left,ic,FALSE);
11232
11233   /* if the value is already in a pointer register
11234        then don't need anything more */
11235     if (!AOP_INPREG(AOP(left))) {
11236         /* otherwise get a free pointer register */
11237         aop = newAsmop(0);
11238         preg = getFreePtr(ic,&aop,FALSE);
11239         pic16_emitcode("mov","%s,%s",
11240                 preg->name,
11241                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11242         rname = preg->name ;
11243     } else
11244         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11245     
11246     pic16_freeAsmop(left,NULL,ic,TRUE);
11247     pic16_aopOp (result,ic,FALSE);
11248
11249     /* if bitfield then unpack the bits */
11250     if (IS_BITFIELD(retype)) 
11251         genUnpackBits (result,left,rname,PPOINTER);
11252     else {
11253         /* we have can just get the values */
11254         int size = AOP_SIZE(result);
11255         int offset = 0 ;        
11256         
11257         while (size--) {
11258             
11259             pic16_emitcode("movx","a,@%s",rname);
11260             pic16_aopPut(AOP(result),"a",offset);
11261             
11262             offset++ ;
11263             
11264             if (size)
11265                 pic16_emitcode("inc","%s",rname);
11266         }
11267     }
11268
11269     /* now some housekeeping stuff */
11270     if (aop) {
11271         /* we had to allocate for this iCode */
11272         pic16_freeAsmop(NULL,aop,ic,TRUE);
11273     } else { 
11274         /* we did not allocate which means left
11275            already in a pointer register, then
11276            if size > 0 && this could be used again
11277            we have to point it back to where it 
11278            belongs */
11279         if (AOP_SIZE(result) > 1 &&
11280             !OP_SYMBOL(left)->remat &&
11281             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11282               ic->depth )) {
11283             int size = AOP_SIZE(result) - 1;
11284             while (size--)
11285                 pic16_emitcode("dec","%s",rname);
11286         }
11287     }
11288
11289     /* done */
11290     pic16_freeAsmop(result,NULL,ic,TRUE);
11291     
11292         
11293 }
11294
11295 /*-----------------------------------------------------------------*/
11296 /* genFarPointerGet - gget value from far space                    */
11297 /*-----------------------------------------------------------------*/
11298 static void genFarPointerGet (operand *left,
11299                               operand *result, iCode *ic)
11300 {
11301     int size, offset ;
11302     sym_link *retype = getSpec(operandType(result));
11303
11304     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11305
11306     pic16_aopOp(left,ic,FALSE);
11307
11308     /* if the operand is already in dptr 
11309     then we do nothing else we move the value to dptr */
11310     if (AOP_TYPE(left) != AOP_STR) {
11311         /* if this is remateriazable */
11312         if (AOP_TYPE(left) == AOP_IMMD)
11313             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11314         else { /* we need to get it byte by byte */
11315             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11316             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11317             if (options.model == MODEL_FLAT24)
11318             {
11319                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11320             }
11321         }
11322     }
11323     /* so dptr know contains the address */
11324     pic16_freeAsmop(left,NULL,ic,TRUE);
11325     pic16_aopOp(result,ic,FALSE);
11326
11327     /* if bit then unpack */
11328     if (IS_BITFIELD(retype)) 
11329         genUnpackBits(result,left,"dptr",FPOINTER);
11330     else {
11331         size = AOP_SIZE(result);
11332         offset = 0 ;
11333
11334         while (size--) {
11335             pic16_emitcode("movx","a,@dptr");
11336             pic16_aopPut(AOP(result),"a",offset++);
11337             if (size)
11338                 pic16_emitcode("inc","dptr");
11339         }
11340     }
11341
11342     pic16_freeAsmop(result,NULL,ic,TRUE);
11343 }
11344
11345 #if 0
11346 /*-----------------------------------------------------------------*/
11347 /* genCodePointerGet - get value from code space                  */
11348 /*-----------------------------------------------------------------*/
11349 static void genCodePointerGet (operand *left,
11350                                 operand *result, iCode *ic)
11351 {
11352     int size, offset ;
11353     sym_link *retype = getSpec(operandType(result));
11354
11355     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11356
11357     pic16_aopOp(left,ic,FALSE);
11358
11359     /* if the operand is already in dptr 
11360     then we do nothing else we move the value to dptr */
11361     if (AOP_TYPE(left) != AOP_STR) {
11362         /* if this is remateriazable */
11363         if (AOP_TYPE(left) == AOP_IMMD)
11364             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11365         else { /* we need to get it byte by byte */
11366             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11367             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11368             if (options.model == MODEL_FLAT24)
11369             {
11370                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11371             }
11372         }
11373     }
11374     /* so dptr know contains the address */
11375     pic16_freeAsmop(left,NULL,ic,TRUE);
11376     pic16_aopOp(result,ic,FALSE);
11377
11378     /* if bit then unpack */
11379     if (IS_BITFIELD(retype)) 
11380         genUnpackBits(result,left,"dptr",CPOINTER);
11381     else {
11382         size = AOP_SIZE(result);
11383         offset = 0 ;
11384
11385         while (size--) {
11386             pic16_emitcode("clr","a");
11387             pic16_emitcode("movc","a,@a+dptr");
11388             pic16_aopPut(AOP(result),"a",offset++);
11389             if (size)
11390                 pic16_emitcode("inc","dptr");
11391         }
11392     }
11393
11394     pic16_freeAsmop(result,NULL,ic,TRUE);
11395 }
11396 #endif
11397
11398 #if 0
11399 /*-----------------------------------------------------------------*/
11400 /* genGenPointerGet - gget value from generic pointer space        */
11401 /*-----------------------------------------------------------------*/
11402 static void genGenPointerGet (operand *left,
11403                               operand *result, iCode *ic)
11404 {
11405   int size, offset, lit;
11406   sym_link *retype = getSpec(operandType(result));
11407
11408         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11409         pic16_aopOp(left,ic,FALSE);
11410         pic16_aopOp(result,ic,FALSE);
11411         size = AOP_SIZE(result);
11412
11413         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11414
11415         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11416
11417                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11418                 // load FSR0 from immediate
11419                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11420
11421 //              pic16_loadFSR0( left );
11422
11423                 offset = 0;
11424                 while(size--) {
11425                         if(size) {
11426                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11427                         } else {
11428                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11429                         }
11430                         offset++;
11431                 }
11432                 goto release;
11433
11434         }
11435         else { /* we need to get it byte by byte */
11436                 // set up FSR0 with address from left
11437                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11438                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11439
11440                 offset = 0 ;
11441
11442                 while(size--) {
11443                         if(size) {
11444                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11445                         } else {
11446                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11447                         }
11448                         offset++;
11449                 }
11450                 goto release;
11451         }
11452
11453   /* if bit then unpack */
11454         if (IS_BITFIELD(retype)) 
11455                 genUnpackBits(result,left,"BAD",GPOINTER);
11456
11457         release:
11458         pic16_freeAsmop(left,NULL,ic,TRUE);
11459         pic16_freeAsmop(result,NULL,ic,TRUE);
11460
11461 }
11462 #endif
11463
11464
11465 /*-----------------------------------------------------------------*/
11466 /* genGenPointerGet - gget value from generic pointer space        */
11467 /*-----------------------------------------------------------------*/
11468 static void genGenPointerGet (operand *left,
11469                               operand *result, iCode *ic)
11470 {
11471   int size, offset, lit;
11472   sym_link *retype = getSpec(operandType(result));
11473   char fgptrget[32];
11474
11475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11476     pic16_aopOp(left,ic,FALSE);
11477     pic16_aopOp(result,ic,FALSE);
11478     size = AOP_SIZE(result);
11479
11480     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11481
11482     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11483
11484       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11485       // load FSR0 from immediate
11486       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11487
11488       werror(W_POSSBUG2, __FILE__, __LINE__);
11489
11490       offset = 0;
11491       while(size--) {
11492         if(size) {
11493           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11494         } else {
11495           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11496         }
11497         offset++;
11498       }
11499
11500       goto release;
11501
11502     } else { /* we need to get it byte by byte */
11503
11504       /* set up WREG:PRODL:FSR0L with address from left */
11505       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11506       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11507       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11508       
11509       switch( size ) {
11510         case 1: strcpy(fgptrget, "__gptrget1"); break;
11511         case 2: strcpy(fgptrget, "__gptrget2"); break;
11512         case 3: strcpy(fgptrget, "__gptrget3"); break;
11513         case 4: strcpy(fgptrget, "__gptrget4"); break;
11514         default:
11515           werror(W_POSSBUG2, __FILE__, __LINE__);
11516           abort();
11517       }
11518       
11519       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11520       
11521       assignResultValue(result, 1);
11522       
11523       {
11524         symbol *sym;
11525
11526           sym = newSymbol( fgptrget, 0 );
11527           strcpy(sym->rname, fgptrget);
11528           checkAddSym(&externs, sym);
11529
11530 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11531       }
11532               
11533       goto release;
11534     }
11535
11536   /* if bit then unpack */
11537     if (IS_BITFIELD(retype)) 
11538       genUnpackBits(result,left,"BAD",GPOINTER);
11539
11540 release:
11541   pic16_freeAsmop(left,NULL,ic,TRUE);
11542   pic16_freeAsmop(result,NULL,ic,TRUE);
11543 }
11544
11545 /*-----------------------------------------------------------------*/
11546 /* genConstPointerGet - get value from const generic pointer space */
11547 /*-----------------------------------------------------------------*/
11548 static void genConstPointerGet (operand *left,
11549                                 operand *result, iCode *ic)
11550 {
11551   //sym_link *retype = getSpec(operandType(result));
11552   // symbol *albl = newiTempLabel(NULL);        // patch 15
11553   // symbol *blbl = newiTempLabel(NULL);        //
11554   // PIC_OPCODE poc;                            // patch 15
11555   int size;
11556   int offset = 0;
11557
11558   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11559   pic16_aopOp(left,ic,FALSE);
11560   pic16_aopOp(result,ic,TRUE);
11561   size = AOP_SIZE(result);
11562
11563   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11564
11565   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11566
11567   // set up table pointer
11568   if( (AOP_TYPE(left) == AOP_PCODE) 
11569       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11570           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11571     {
11572       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11573       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11574       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11575       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11576       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11577       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11578   } else {
11579     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11580     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11581     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11582   }
11583
11584   while(size--) {
11585     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11586     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11587     offset++;
11588   }
11589     
11590   pic16_freeAsmop(left,NULL,ic,TRUE);
11591   pic16_freeAsmop(result,NULL,ic,TRUE);
11592 }
11593
11594
11595 /*-----------------------------------------------------------------*/
11596 /* genPointerGet - generate code for pointer get                   */
11597 /*-----------------------------------------------------------------*/
11598 static void genPointerGet (iCode *ic)
11599 {
11600   operand *left, *result ;
11601   sym_link *type, *etype;
11602   int p_type;
11603
11604     FENTRY;
11605     
11606     left = IC_LEFT(ic);
11607     result = IC_RESULT(ic) ;
11608
11609     /* depending on the type of pointer we need to
11610     move it to the correct pointer register */
11611     type = operandType(left);
11612     etype = getSpec(type);
11613
11614 #if 0
11615     if (IS_PTR_CONST(type))
11616 #else
11617     if (IS_CODEPTR(type))
11618 #endif
11619       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11620
11621     /* if left is of type of pointer then it is simple */
11622     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11623       p_type = DCL_TYPE(type);
11624     else {
11625       /* we have to go by the storage class */
11626       p_type = PTR_TYPE(SPEC_OCLS(etype));
11627
11628       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11629
11630       if (SPEC_OCLS(etype)->codesp ) {
11631         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11632         //p_type = CPOINTER ;   
11633       } else
11634       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11635         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11636         /*p_type = FPOINTER ;*/ 
11637       } else
11638       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11639         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11640         /* p_type = PPOINTER; */
11641       } else
11642       if (SPEC_OCLS(etype) == idata ) {
11643         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11644         /* p_type = IPOINTER; */
11645       } else {
11646         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11647         /* p_type = POINTER ; */
11648       }
11649     }
11650
11651     /* now that we have the pointer type we assign
11652     the pointer values */
11653     switch (p_type) {
11654       case POINTER:     
11655       case IPOINTER:
11656         genNearPointerGet (left,result,ic);
11657         break;
11658
11659       case PPOINTER:
11660         genPagedPointerGet(left,result,ic);
11661         break;
11662
11663       case FPOINTER:
11664         genFarPointerGet (left,result,ic);
11665         break;
11666
11667       case CPOINTER:
11668         genConstPointerGet (left,result,ic);
11669         //pic16_emitcodePointerGet (left,result,ic);
11670         break;
11671
11672       case GPOINTER:
11673 #if 0
11674       if (IS_PTR_CONST(type))
11675         genConstPointerGet (left,result,ic);
11676       else
11677 #endif
11678         genGenPointerGet (left,result,ic);
11679       break;
11680
11681     default:
11682       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11683               "genPointerGet: illegal pointer type");
11684     
11685     }
11686 }
11687
11688 /*-----------------------------------------------------------------*/
11689 /* genPackBits - generates code for packed bit storage             */
11690 /*-----------------------------------------------------------------*/
11691 static void genPackBits (sym_link    *etype , operand *result,
11692                          operand *right ,
11693                          char *rname, int p_type)
11694 {
11695   int shCnt = 0 ;
11696   int offset = 0  ;
11697   int rLen = 0 ;
11698   int blen, bstr ;   
11699   sym_link *retype;
11700   char *l ;
11701
11702         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11703         blen = SPEC_BLEN(etype);
11704         bstr = SPEC_BSTR(etype);
11705
11706         retype = getSpec(operandType(right));
11707
11708         if(AOP_TYPE(right) == AOP_LIT) {
11709                 if((blen == 1) && (bstr < 8)) {
11710                   unsigned long lit;
11711                         /* it is a single bit, so use the appropriate bit instructions */
11712
11713                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11714
11715                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11716 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11717                         if((p_type == POINTER) && (result)) {
11718                                 /* workaround to reduce the extra lfsr instruction */
11719                                 if(lit) {
11720                                         pic16_emitpcode(POC_BSF,
11721                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11722                                 } else {
11723                                         pic16_emitpcode(POC_BCF,
11724                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11725                                 }
11726                         } else {
11727                                 pic16_loadFSR0( result );
11728                                 if(lit) {
11729                                         pic16_emitpcode(POC_BSF,
11730                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11731                                 } else {
11732                                         pic16_emitpcode(POC_BCF,
11733                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11734                                 }
11735                         }
11736         
11737                   return;
11738                 }
11739
11740                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11741                 offset++;
11742         } else
11743         if(IS_BITFIELD(retype) 
11744           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11745           && (blen == 1)) {
11746           int rblen, rbstr;
11747
11748             rblen = SPEC_BLEN( retype );
11749             rbstr = SPEC_BSTR( retype );
11750             
11751
11752             if(IS_BITFIELD(etype)) {
11753               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11754               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11755             } else {
11756               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11757             }
11758             
11759             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11760             
11761             if(IS_BITFIELD(etype)) {
11762               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11763             } else {
11764               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11765             }
11766
11767             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11768             
11769             return;
11770         } else
11771           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11772
11773         /* if the bit lenth is less than or    */
11774         /* it exactly fits a byte then         */
11775         if((shCnt=SPEC_BSTR(etype))
11776                 || SPEC_BLEN(etype) <= 8 )  {
11777
11778                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11779
11780                 /* shift left acc */
11781                 AccLsh(shCnt);
11782
11783                 /* using PRODL as a temporary register here */
11784                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11785
11786                 switch (p_type) {
11787                         case FPOINTER:
11788                         case POINTER:
11789                                 pic16_loadFSR0( result );
11790                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11791 //                              pic16_emitcode ("mov","b,a");
11792 //                              pic16_emitcode("mov","a,@%s",rname);
11793                                 break;
11794
11795                         case GPOINTER:
11796                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11797                                 break;
11798
11799                 }
11800 #if 1
11801                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11802                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11803                                         (unsigned char)(0xff >> (8-bstr))) ));
11804                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11805                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11806 #endif
11807
11808           return;
11809         }
11810
11811
11812         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11813         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11814         exit(-1);
11815
11816
11817     /* if we r done */
11818     if ( SPEC_BLEN(etype) <= 8 )
11819         return ;
11820
11821     pic16_emitcode("inc","%s",rname);
11822     rLen = SPEC_BLEN(etype) ;     
11823
11824
11825
11826     /* now generate for lengths greater than one byte */
11827     while (1) {
11828
11829         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11830
11831         rLen -= 8 ;
11832         if (rLen <= 0 )
11833             break ;
11834
11835         switch (p_type) {
11836             case POINTER:
11837                 if (*l == '@') {
11838                     MOVA(l);
11839                     pic16_emitcode("mov","@%s,a",rname);
11840                 } else
11841                     pic16_emitcode("mov","@%s,%s",rname,l);
11842                 break;
11843
11844             case FPOINTER:
11845                 MOVA(l);
11846                 pic16_emitcode("movx","@dptr,a");
11847                 break;
11848
11849             case GPOINTER:
11850                 MOVA(l);
11851                 DEBUGpic16_emitcode(";lcall","__gptrput");
11852                 break;  
11853         }   
11854         pic16_emitcode ("inc","%s",rname);
11855     }
11856
11857     MOVA(l);
11858
11859     /* last last was not complete */
11860     if (rLen)   {
11861         /* save the byte & read byte */
11862         switch (p_type) {
11863             case POINTER:
11864                 pic16_emitcode ("mov","b,a");
11865                 pic16_emitcode("mov","a,@%s",rname);
11866                 break;
11867
11868             case FPOINTER:
11869                 pic16_emitcode ("mov","b,a");
11870                 pic16_emitcode("movx","a,@dptr");
11871                 break;
11872
11873             case GPOINTER:
11874                 pic16_emitcode ("push","b");
11875                 pic16_emitcode ("push","acc");
11876                 pic16_emitcode ("lcall","__gptrget");
11877                 pic16_emitcode ("pop","b");
11878                 break;
11879         }
11880
11881         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11882         pic16_emitcode ("orl","a,b");
11883     }
11884
11885     if (p_type == GPOINTER)
11886         pic16_emitcode("pop","b");
11887
11888     switch (p_type) {
11889
11890     case POINTER:
11891         pic16_emitcode("mov","@%s,a",rname);
11892         break;
11893         
11894     case FPOINTER:
11895         pic16_emitcode("movx","@dptr,a");
11896         break;
11897         
11898     case GPOINTER:
11899         DEBUGpic16_emitcode(";lcall","__gptrput");
11900         break;                  
11901     }
11902 }
11903 /*-----------------------------------------------------------------*/
11904 /* genDataPointerSet - remat pointer to data space                 */
11905 /*-----------------------------------------------------------------*/
11906 static void genDataPointerSet(operand *right,
11907                               operand *result,
11908                               iCode *ic)
11909 {
11910     int size, offset = 0, resoffset=0 ;
11911
11912     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11913     pic16_aopOp(right,ic,FALSE);
11914
11915     size = AOP_SIZE(right);
11916
11917 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11918
11919 #if 0
11920     if ( AOP_TYPE(result) == AOP_PCODE) {
11921       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11922               AOP(result)->aopu.pcop->name,
11923                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11924               PCOR(AOP(result)->aopu.pcop)->instance:
11925               PCOI(AOP(result)->aopu.pcop)->offset);
11926     }
11927 #endif
11928
11929         if(AOP(result)->aopu.pcop->type == PO_DIR)
11930                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11931
11932         while (size--) {
11933                 if (AOP_TYPE(right) == AOP_LIT) {
11934                   unsigned int lit;
11935
11936                     if(!IS_FLOAT(operandType( right )))
11937                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11938                     else {
11939                       union {
11940                         unsigned long lit_int;
11941                         float lit_float;
11942                       } info;
11943         
11944                         /* take care if literal is a float */
11945                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11946                         lit = info.lit_int;
11947                     }
11948
11949                     lit = lit >> (8*offset);
11950                     if(lit&0xff) {
11951                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11952                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11953                     } else {
11954                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11955                     }
11956                 } else {
11957                   pic16_mov2w(AOP(right), offset);
11958                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11959                 }
11960                 offset++;
11961                 resoffset++;
11962         }
11963
11964     pic16_freeAsmop(right,NULL,ic,TRUE);
11965 }
11966
11967
11968
11969 /*-----------------------------------------------------------------*/
11970 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11971 /*-----------------------------------------------------------------*/
11972 static void genNearPointerSet (operand *right,
11973                                operand *result, 
11974                                iCode *ic)
11975 {
11976   asmop *aop = NULL;
11977   char *l;
11978   sym_link *retype;
11979   sym_link *ptype = operandType(result);
11980   sym_link *resetype;
11981     
11982         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11983         retype= getSpec(operandType(right));
11984         resetype = getSpec(operandType(result));
11985   
11986         pic16_aopOp(result,ic,FALSE);
11987     
11988         /* if the result is rematerializable &
11989          * in data space & not a bit variable */
11990         
11991         /* and result is not a bit variable */
11992         if (AOP_TYPE(result) == AOP_PCODE
11993 //              && AOP_TYPE(result) == AOP_IMMD
11994                 && DCL_TYPE(ptype) == POINTER
11995                 && !IS_BITFIELD(retype)
11996                 && !IS_BITFIELD(resetype)) {
11997
11998                 genDataPointerSet (right,result,ic);
11999                 pic16_freeAsmop(result,NULL,ic,TRUE);
12000           return;
12001         }
12002
12003         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004         pic16_aopOp(right,ic,FALSE);
12005         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12006
12007         /* if the value is already in a pointer register
12008          * then don't need anything more */
12009         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12010                 /* otherwise get a free pointer register */
12011                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12012
12013 //              if( (AOP_TYPE(result) == AOP_PCODE) 
12014 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12015 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12016                 if(is_LitAOp( AOP(result) ))
12017                 {
12018                   if(!IS_BITFIELD(resetype))
12019                         pic16_loadFSR0( result );  // patch 10
12020                 } else {
12021                   if(!IS_BITFIELD(resetype)) {
12022                         // set up FSR0 with address of result
12023                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12024                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12025                   }
12026                 }
12027
12028         }
12029 //      else
12030 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12031
12032         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12033
12034 //      pic16_loadFSR0( result );
12035
12036         /* if bitfield then unpack the bits */
12037         if (IS_BITFIELD(resetype)) {
12038                 genPackBits (resetype, result, right, NULL, POINTER);
12039         } else {
12040                 /* we have can just get the values */
12041           int size = AOP_SIZE(right);
12042           int offset = 0 ;    
12043
12044                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12045                 while (size--) {
12046                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12047                         if (*l == '@' ) {
12048                                 //MOVA(l);
12049                                 //pic16_emitcode("mov","@%s,a",rname);
12050                                 pic16_emitcode("movf","indf0,w ;1");
12051                         } else {
12052
12053                                 if (AOP_TYPE(right) == AOP_LIT) {
12054                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12055                                         if (size) {
12056                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12057                                         } else {
12058                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12059                                         }
12060                                 } else { // no literal
12061                                         if(size) {
12062                                                 pic16_emitpcode(POC_MOVFF,
12063                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12064                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12065                                         } else {
12066                                                 pic16_emitpcode(POC_MOVFF,
12067                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12068                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12069                                         }
12070                                 }
12071                         }
12072                         offset++;
12073                 }
12074         }
12075
12076         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12077         /* now some housekeeping stuff */
12078         if (aop) {
12079                 /* we had to allocate for this iCode */
12080                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12081         } else { 
12082                 /* we did not allocate which means left
12083                  * already in a pointer register, then
12084                  * if size > 0 && this could be used again
12085                  * we have to point it back to where it 
12086                  * belongs */
12087                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12088                 if (AOP_SIZE(right) > 1
12089                         && !OP_SYMBOL(result)->remat
12090                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12091                                 || ic->depth )) {
12092
12093                   int size = AOP_SIZE(right) - 1;
12094
12095                         while (size--)
12096                                 pic16_emitcode("decf","fsr0,f");
12097                         //pic16_emitcode("dec","%s",rname);
12098                 }
12099         }
12100
12101         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12102         /* done */
12103 //release:
12104         pic16_freeAsmop(right,NULL,ic,TRUE);
12105         pic16_freeAsmop(result,NULL,ic,TRUE);
12106 }
12107
12108 /*-----------------------------------------------------------------*/
12109 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12110 /*-----------------------------------------------------------------*/
12111 static void genPagedPointerSet (operand *right,
12112                                operand *result, 
12113                                iCode *ic)
12114 {
12115     asmop *aop = NULL;
12116     regs *preg = NULL ;
12117     char *rname , *l;
12118     sym_link *retype;
12119        
12120     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12121
12122     retype= getSpec(operandType(right));
12123     
12124     pic16_aopOp(result,ic,FALSE);
12125     
12126     /* if the value is already in a pointer register
12127        then don't need anything more */
12128     if (!AOP_INPREG(AOP(result))) {
12129         /* otherwise get a free pointer register */
12130         aop = newAsmop(0);
12131         preg = getFreePtr(ic,&aop,FALSE);
12132         pic16_emitcode("mov","%s,%s",
12133                 preg->name,
12134                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12135         rname = preg->name ;
12136     } else
12137         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12138     
12139     pic16_freeAsmop(result,NULL,ic,TRUE);
12140     pic16_aopOp (right,ic,FALSE);
12141
12142     /* if bitfield then unpack the bits */
12143     if (IS_BITFIELD(retype)) 
12144         genPackBits (retype,result,right,rname,PPOINTER);
12145     else {
12146         /* we have can just get the values */
12147         int size = AOP_SIZE(right);
12148         int offset = 0 ;        
12149         
12150         while (size--) {
12151             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12152             
12153             MOVA(l);
12154             pic16_emitcode("movx","@%s,a",rname);
12155
12156             if (size)
12157                 pic16_emitcode("inc","%s",rname);
12158
12159             offset++;
12160         }
12161     }
12162     
12163     /* now some housekeeping stuff */
12164     if (aop) {
12165         /* we had to allocate for this iCode */
12166         pic16_freeAsmop(NULL,aop,ic,TRUE);
12167     } else { 
12168         /* we did not allocate which means left
12169            already in a pointer register, then
12170            if size > 0 && this could be used again
12171            we have to point it back to where it 
12172            belongs */
12173         if (AOP_SIZE(right) > 1 &&
12174             !OP_SYMBOL(result)->remat &&
12175             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12176               ic->depth )) {
12177             int size = AOP_SIZE(right) - 1;
12178             while (size--)
12179                 pic16_emitcode("dec","%s",rname);
12180         }
12181     }
12182
12183     /* done */
12184     pic16_freeAsmop(right,NULL,ic,TRUE);
12185     
12186         
12187 }
12188
12189 /*-----------------------------------------------------------------*/
12190 /* genFarPointerSet - set value from far space                     */
12191 /*-----------------------------------------------------------------*/
12192 static void genFarPointerSet (operand *right,
12193                               operand *result, iCode *ic)
12194 {
12195     int size, offset ;
12196     sym_link *retype = getSpec(operandType(right));
12197
12198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12199     pic16_aopOp(result,ic,FALSE);
12200
12201     /* if the operand is already in dptr 
12202     then we do nothing else we move the value to dptr */
12203     if (AOP_TYPE(result) != AOP_STR) {
12204         /* if this is remateriazable */
12205         if (AOP_TYPE(result) == AOP_IMMD)
12206             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12207         else { /* we need to get it byte by byte */
12208             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12209             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12210             if (options.model == MODEL_FLAT24)
12211             {
12212                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12213             }
12214         }
12215     }
12216     /* so dptr know contains the address */
12217     pic16_freeAsmop(result,NULL,ic,TRUE);
12218     pic16_aopOp(right,ic,FALSE);
12219
12220     /* if bit then unpack */
12221     if (IS_BITFIELD(retype)) 
12222         genPackBits(retype,result,right,"dptr",FPOINTER);
12223     else {
12224         size = AOP_SIZE(right);
12225         offset = 0 ;
12226
12227         while (size--) {
12228             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12229             MOVA(l);
12230             pic16_emitcode("movx","@dptr,a");
12231             if (size)
12232                 pic16_emitcode("inc","dptr");
12233         }
12234     }
12235
12236     pic16_freeAsmop(right,NULL,ic,TRUE);
12237 }
12238
12239 /*-----------------------------------------------------------------*/
12240 /* genGenPointerSet - set value from generic pointer space         */
12241 /*-----------------------------------------------------------------*/
12242 #if 0
12243 static void genGenPointerSet (operand *right,
12244                               operand *result, iCode *ic)
12245 {
12246         int i, size, offset, lit;
12247         sym_link *retype = getSpec(operandType(right));
12248
12249         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12250
12251         pic16_aopOp(result,ic,FALSE);
12252         pic16_aopOp(right,ic,FALSE);
12253         size = AOP_SIZE(right);
12254         offset = 0;
12255
12256         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12257
12258         /* if the operand is already in dptr 
12259                 then we do nothing else we move the value to dptr */
12260         if (AOP_TYPE(result) != AOP_STR) {
12261                 /* if this is remateriazable */
12262                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12263                 // WARNING: anythig until "else" is untested!
12264                 if (AOP_TYPE(result) == AOP_IMMD) {
12265                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12266                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12267                         // load FSR0 from immediate
12268                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12269                         offset = 0;
12270                         while(size--) {
12271                                 if(size) {
12272                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12273                                 } else {
12274                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12275                                 }
12276                                 offset++;
12277                         }
12278                         goto release;
12279                 }
12280                 else { /* we need to get it byte by byte */
12281                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12282                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12283
12284                         // set up FSR0 with address of result
12285                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12286                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12287
12288                         /* hack hack! see if this the FSR. If so don't load W */
12289                         if(AOP_TYPE(right) != AOP_ACC) {
12290
12291                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12292
12293                                 if(AOP_TYPE(right) == AOP_LIT)
12294                                 {
12295                                         // copy literal
12296                                         // note: pic16_popGet handles sign extension
12297                                         for(i=0;i<size;i++) {
12298                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12299                                                 if(i < size-1)
12300                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12301                                                 else
12302                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12303                                         }
12304                                 } else {
12305                                         // copy regs
12306
12307                                         for(i=0;i<size;i++) {
12308                                                 if(i < size-1)
12309                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12310                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12311                                                 else
12312                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12313                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12314                                         }
12315                                 }
12316                                 goto release;
12317                         } 
12318                         // right = ACC
12319                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12320                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12321                         goto release;
12322         } // if (AOP_TYPE(result) != AOP_IMMD)
12323
12324         } // if (AOP_TYPE(result) != AOP_STR)
12325         /* so dptr know contains the address */
12326
12327
12328         /* if bit then unpack */
12329         if (IS_BITFIELD(retype)) 
12330                 genPackBits(retype,result,right,"dptr",GPOINTER);
12331         else {
12332                 size = AOP_SIZE(right);
12333                 offset = 0 ;
12334
12335                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12336
12337                 // set up FSR0 with address of result
12338                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12339                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12340         
12341                 while (size--) {
12342                         if (AOP_TYPE(right) == AOP_LIT) {
12343                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12344                                 if (size) {
12345                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12346                                 } else {
12347                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12348                                 }
12349                         } else { // no literal
12350                                 if(size) {
12351                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12352                                 } else {
12353                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12354                                 }
12355                         }
12356                         offset++;
12357                 }
12358         }
12359
12360         release:
12361         pic16_freeAsmop(right,NULL,ic,TRUE);
12362         pic16_freeAsmop(result,NULL,ic,TRUE);
12363 }
12364 #endif
12365
12366 static void genGenPointerSet (operand *right,
12367                               operand *result, iCode *ic)
12368 {
12369   int size;
12370   sym_link *retype = getSpec(operandType(right));
12371   char fgptrput[32];
12372
12373     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12374
12375     pic16_aopOp(result,ic,FALSE);
12376     pic16_aopOp(right,ic,FALSE);
12377     size = AOP_SIZE(right);
12378
12379     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12380
12381
12382     /* if bit then unpack */
12383     if (IS_BITFIELD(retype)) {
12384 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12385       genPackBits(retype,result,right,"dptr",GPOINTER);
12386       goto release;
12387     }
12388
12389     size = AOP_SIZE(right);
12390
12391     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12392
12393
12394
12395     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12396
12397     /* value of right+0 is placed on stack, which will be retrieved
12398      * by the support function this restoring the stack. The important
12399      * thing is that there is no need to manually restore stack pointer
12400      * here */
12401     pushaop(AOP(right), 0);
12402 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12403     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12404     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12405     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12406     
12407     /* load address to write to in WREG:FSR0H:FSR0L */
12408     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12409                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12410     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12411                                 pic16_popCopyReg(&pic16_pc_prodl)));
12412     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12413     
12414
12415     /* put code here */
12416     switch (size) {
12417       case 1: strcpy(fgptrput, "__gptrput1"); break;
12418       case 2: strcpy(fgptrput, "__gptrput2"); break;
12419       case 3: strcpy(fgptrput, "__gptrput3"); break;
12420       case 4: strcpy(fgptrput, "__gptrput4"); break;
12421       default:
12422         werror(W_POSSBUG2, __FILE__, __LINE__);
12423         abort();
12424     }
12425     
12426     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12427     
12428     {
12429       symbol *sym;
12430                   
12431         sym = newSymbol( fgptrput, 0 );
12432         strcpy(sym->rname, fgptrput);
12433         checkAddSym(&externs, sym);
12434     }
12435
12436 release:
12437     pic16_freeAsmop(right,NULL,ic,TRUE);
12438     pic16_freeAsmop(result,NULL,ic,TRUE);
12439 }
12440
12441 /*-----------------------------------------------------------------*/
12442 /* genPointerSet - stores the value into a pointer location        */
12443 /*-----------------------------------------------------------------*/
12444 static void genPointerSet (iCode *ic)
12445 {    
12446   operand *right, *result ;
12447   sym_link *type, *etype;
12448   int p_type;
12449
12450     FENTRY;
12451
12452     right = IC_RIGHT(ic);
12453     result = IC_RESULT(ic) ;
12454
12455     /* depending on the type of pointer we need to
12456     move it to the correct pointer register */
12457     type = operandType(result);
12458     etype = getSpec(type);
12459     /* if left is of type of pointer then it is simple */
12460     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12461         p_type = DCL_TYPE(type);
12462     }
12463     else {
12464         /* we have to go by the storage class */
12465         p_type = PTR_TYPE(SPEC_OCLS(etype));
12466
12467 /*      if (SPEC_OCLS(etype)->codesp ) { */
12468 /*          p_type = CPOINTER ;  */
12469 /*      } */
12470 /*      else */
12471 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12472 /*              p_type = FPOINTER ; */
12473 /*          else */
12474 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12475 /*                  p_type = PPOINTER ; */
12476 /*              else */
12477 /*                  if (SPEC_OCLS(etype) == idata ) */
12478 /*                      p_type = IPOINTER ; */
12479 /*                  else */
12480 /*                      p_type = POINTER ; */
12481     }
12482
12483     /* now that we have the pointer type we assign
12484     the pointer values */
12485     switch (p_type) {
12486       case POINTER:
12487       case IPOINTER:
12488         genNearPointerSet (right,result,ic);
12489         break;
12490
12491       case PPOINTER:
12492         genPagedPointerSet (right,result,ic);
12493         break;
12494
12495       case FPOINTER:
12496         genFarPointerSet (right,result,ic);
12497         break;
12498         
12499       case GPOINTER:
12500         genGenPointerSet (right,result,ic);
12501         break;
12502
12503       default:
12504         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12505           "genPointerSet: illegal pointer type");
12506     }
12507 }
12508
12509 /*-----------------------------------------------------------------*/
12510 /* genIfx - generate code for Ifx statement                        */
12511 /*-----------------------------------------------------------------*/
12512 static void genIfx (iCode *ic, iCode *popIc)
12513 {
12514   operand *cond = IC_COND(ic);
12515   int isbit =0;
12516
12517     FENTRY;
12518
12519     pic16_aopOp(cond,ic,FALSE);
12520
12521     /* get the value into acc */
12522     if (AOP_TYPE(cond) != AOP_CRY)
12523       pic16_toBoolean(cond);
12524     else
12525       isbit = 1;
12526     /* the result is now in the accumulator */
12527     pic16_freeAsmop(cond,NULL,ic,TRUE);
12528
12529     /* if there was something to be popped then do it */
12530     if (popIc)
12531       genIpop(popIc);
12532
12533     /* if the condition is  a bit variable */
12534     if (isbit && IS_ITEMP(cond) && 
12535         SPIL_LOC(cond)) {
12536       genIfxJump(ic,"c");
12537       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12538     } else {
12539       if (isbit && !IS_ITEMP(cond))
12540         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12541         else
12542         genIfxJump(ic,"a");
12543     }
12544     ic->generated = 1;
12545 }
12546
12547 /*-----------------------------------------------------------------*/
12548 /* genAddrOf - generates code for address of                       */
12549 /*-----------------------------------------------------------------*/
12550 static void genAddrOf (iCode *ic)
12551 {
12552   operand *result, *left;
12553   int size;
12554   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12555   pCodeOp *pcop0, *pcop1, *pcop2;
12556
12557     FENTRY;
12558
12559     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12560
12561     sym = OP_SYMBOL( IC_LEFT(ic) );
12562     
12563     if(sym->onStack) {
12564       /* get address of symbol on stack */
12565       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12566 #if 0
12567       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12568                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12569 #endif
12570
12571       // operands on stack are accessible via "FSR2 + index" with index
12572       // starting at 2 for arguments and growing from 0 downwards for
12573       // local variables (index == 0 is not assigned so we add one here)
12574       {
12575         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12576         if (soffs <= 0) {
12577           assert (soffs < 0);
12578           soffs++;
12579         } // if
12580         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12581         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12582         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12583         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12584         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12585         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12586         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12587       }
12588
12589       goto release;
12590     }
12591         
12592 //      if(pic16_debug_verbose) {
12593 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12594 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12595 //      }
12596         
12597     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12598     size = AOP_SIZE(IC_RESULT(ic));
12599
12600     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12601     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12602     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12603         
12604     if (size == 3) {
12605       pic16_emitpcode(POC_MOVLW, pcop0);
12606       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12607       pic16_emitpcode(POC_MOVLW, pcop1);
12608       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12609       pic16_emitpcode(POC_MOVLW, pcop2);
12610       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12611     } else
12612     if (size == 2) {
12613       pic16_emitpcode(POC_MOVLW, pcop0);
12614       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12615       pic16_emitpcode(POC_MOVLW, pcop1);
12616     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12617     } else {
12618       pic16_emitpcode(POC_MOVLW, pcop0);
12619       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12620     }
12621
12622     pic16_freeAsmop(left, NULL, ic, FALSE);
12623 release:
12624     pic16_freeAsmop(result,NULL,ic,TRUE);
12625 }
12626
12627
12628 #if 0
12629 /*-----------------------------------------------------------------*/
12630 /* genFarFarAssign - assignment when both are in far space         */
12631 /*-----------------------------------------------------------------*/
12632 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12633 {
12634     int size = AOP_SIZE(right);
12635     int offset = 0;
12636     char *l ;
12637     /* first push the right side on to the stack */
12638     while (size--) {
12639         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12640         MOVA(l);
12641         pic16_emitcode ("push","acc");
12642     }
12643     
12644     pic16_freeAsmop(right,NULL,ic,FALSE);
12645     /* now assign DPTR to result */
12646     pic16_aopOp(result,ic,FALSE);
12647     size = AOP_SIZE(result);
12648     while (size--) {
12649         pic16_emitcode ("pop","acc");
12650         pic16_aopPut(AOP(result),"a",--offset);
12651     }
12652     pic16_freeAsmop(result,NULL,ic,FALSE);
12653         
12654 }
12655 #endif
12656
12657 /*-----------------------------------------------------------------*/
12658 /* genAssign - generate code for assignment                        */
12659 /*-----------------------------------------------------------------*/
12660 static void genAssign (iCode *ic)
12661 {
12662   operand *result, *right;
12663   int size, offset,know_W;
12664   unsigned long lit = 0L;
12665
12666   result = IC_RESULT(ic);
12667   right  = IC_RIGHT(ic) ;
12668
12669   FENTRY;
12670   
12671   /* if they are the same */
12672   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12673     return ;
12674
12675   /* reversed order operands are aopOp'ed so that result operand
12676    * is effective in case right is a stack symbol. This maneauver
12677    * allows to use the _G.resDirect flag later */
12678   pic16_aopOp(result,ic,TRUE);
12679   pic16_aopOp(right,ic,FALSE);
12680
12681   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12682
12683   /* if they are the same registers */
12684   if (pic16_sameRegs(AOP(right),AOP(result)))
12685     goto release;
12686
12687   /* if the result is a bit */
12688   if (AOP_TYPE(result) == AOP_CRY) {
12689     /* if the right size is a literal then
12690        we know what the value is */
12691     if (AOP_TYPE(right) == AOP_LIT) {
12692           
12693       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12694                   pic16_popGet(AOP(result),0));
12695
12696       if (((int) operandLitValue(right))) 
12697         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12698                        AOP(result)->aopu.aop_dir,
12699                        AOP(result)->aopu.aop_dir);
12700       else
12701         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12702                        AOP(result)->aopu.aop_dir,
12703                        AOP(result)->aopu.aop_dir);
12704       goto release;
12705     }
12706
12707     /* the right is also a bit variable */
12708     if (AOP_TYPE(right) == AOP_CRY) {
12709       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12710       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12711       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12712
12713       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12714                      AOP(result)->aopu.aop_dir,
12715                      AOP(result)->aopu.aop_dir);
12716       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12717                      AOP(right)->aopu.aop_dir,
12718                      AOP(right)->aopu.aop_dir);
12719       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12720                      AOP(result)->aopu.aop_dir,
12721                      AOP(result)->aopu.aop_dir);
12722       goto release ;
12723     }
12724
12725     /* we need to or */
12726     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12727     pic16_toBoolean(right);
12728     emitSKPZ;
12729     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12730     //pic16_aopPut(AOP(result),"a",0);
12731     goto release ;
12732   }
12733
12734   /* bit variables done */
12735   /* general case */
12736   size = AOP_SIZE(result);
12737   offset = 0 ;
12738
12739   if(AOP_TYPE(right) == AOP_LIT) {
12740         if(!IS_FLOAT(operandType( right )))
12741                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12742         else {
12743            union {
12744               unsigned long lit_int;
12745               float lit_float;
12746             } info;
12747         
12748                 /* take care if literal is a float */
12749                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12750                 lit = info.lit_int;
12751         }
12752   }
12753
12754 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12755 //                      sizeof(unsigned long int), sizeof(float));
12756
12757
12758   if (AOP_TYPE(right) == AOP_REG) {
12759     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12760     while (size--) {
12761       
12762       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12763     } // while
12764     goto release;
12765   }
12766
12767   if(AOP_TYPE(right) != AOP_LIT
12768         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12769         && !IS_FUNC(OP_SYM_TYPE(right))
12770         ) {
12771         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12772         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12773
12774         // set up table pointer
12775         if(is_LitOp(right)) {
12776 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12777                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12778                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12779                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12780                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12781                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12782                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12783         } else {
12784 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12785                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12786                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12787                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12788                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12789                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12790                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12791         }
12792
12793         size = min(AOP_SIZE(right), AOP_SIZE(result));
12794         while(size--) {
12795                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12796                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12797                         pic16_popGet(AOP(result),offset)));
12798                 offset++;
12799         }
12800
12801         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12802                 size = AOP_SIZE(result) - AOP_SIZE(right);
12803                 while(size--) {
12804                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12805                         offset++;
12806                 }
12807         }
12808         goto release;
12809   }
12810
12811
12812
12813 #if 0
12814 /* VR - What is this?! */
12815   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12816     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12817     if(aopIdx(AOP(result),0) == 4) {
12818
12819       /* this is a workaround to save value of right into wreg too,
12820        * value of wreg is going to be used later */
12821       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12822       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12823       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12824       goto release;
12825     } else
12826 //      assert(0);
12827       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12828   }
12829 #endif
12830
12831   know_W=-1;
12832   while (size--) {
12833   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12834     if(AOP_TYPE(right) == AOP_LIT) {
12835       if(lit&0xff) {
12836         if(know_W != (lit&0xff))
12837           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12838         know_W = lit&0xff;
12839         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12840       } else
12841         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12842
12843       lit >>= 8;
12844
12845     } else if (AOP_TYPE(right) == AOP_CRY) {
12846       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12847       if(offset == 0) {
12848         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12849         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12850         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12851       }
12852     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12853         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12854         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12855     } else {
12856       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12857
12858       if(!_G.resDirect)         /* use this aopForSym feature */
12859         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12860     }
12861             
12862     offset++;
12863   }
12864   
12865  release:
12866   pic16_freeAsmop (right,NULL,ic,FALSE);
12867   pic16_freeAsmop (result,NULL,ic,TRUE);
12868 }   
12869
12870 /*-----------------------------------------------------------------*/
12871 /* genJumpTab - generates code for jump table                       */
12872 /*-----------------------------------------------------------------*/
12873 static void genJumpTab (iCode *ic)
12874 {
12875   symbol *jtab;
12876   char *l;
12877   pCodeOp *jt_offs;
12878   pCodeOp *jt_offs_hi;
12879   pCodeOp *jt_label;
12880
12881     FENTRY;
12882
12883     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12884     /* get the condition into accumulator */
12885     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12886     MOVA(l);
12887     /* multiply by three */
12888     pic16_emitcode("add","a,acc");
12889     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12890
12891     jtab = newiTempLabel(NULL);
12892     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12893     pic16_emitcode("jmp","@a+dptr");
12894     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12895
12896 #if 0
12897     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12898     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12899     emitSKPNC;
12900     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12901     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12902     pic16_emitpLabel(jtab->key);
12903
12904 #else
12905
12906     jt_offs = pic16_popGetTempReg(0);
12907     jt_offs_hi = pic16_popGetTempReg(1);
12908     jt_label = pic16_popGetLabel (jtab->key);
12909     //fprintf (stderr, "Creating jump table...\n");
12910
12911     // calculate offset into jump table (idx * sizeof (GOTO))
12912     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12913     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12914     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12915     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12916     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12917     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12918     pic16_emitpcode(POC_MOVWF , jt_offs);
12919
12920     // prepare PCLATx (set to first entry in jump table)
12921     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12922     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12923     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12924     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12925     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12926
12927     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12928     pic16_emitpcode(POC_ADDWF , jt_offs);
12929     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12930     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12931     emitSKPNC;
12932     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12933
12934     // release temporaries and prepare jump into table (new PCL --> WREG)
12935     pic16_emitpcode(POC_MOVFW , jt_offs);
12936     pic16_popReleaseTempReg (jt_offs_hi, 1);
12937     pic16_popReleaseTempReg (jt_offs, 0);
12938
12939     // jump into the table
12940     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12941
12942     pic16_emitpLabelFORCE(jtab->key);
12943
12944 #endif
12945     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12946
12947     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12948     /* now generate the jump labels */
12949     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12950          jtab = setNextItem(IC_JTLABELS(ic))) {
12951 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12952         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12953         
12954     }
12955     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12956
12957 }
12958
12959 /*-----------------------------------------------------------------*/
12960 /* genMixedOperation - gen code for operators between mixed types  */
12961 /*-----------------------------------------------------------------*/
12962 /*
12963   TSD - Written for the PIC port - but this unfortunately is buggy.
12964   This routine is good in that it is able to efficiently promote 
12965   types to different (larger) sizes. Unfortunately, the temporary
12966   variables that are optimized out by this routine are sometimes
12967   used in other places. So until I know how to really parse the 
12968   iCode tree, I'm going to not be using this routine :(.
12969 */
12970 static int genMixedOperation (iCode *ic)
12971 {
12972 #if 0
12973   operand *result = IC_RESULT(ic);
12974   sym_link *ctype = operandType(IC_LEFT(ic));
12975   operand *right = IC_RIGHT(ic);
12976   int ret = 0;
12977   int big,small;
12978   int offset;
12979
12980   iCode *nextic;
12981   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12982
12983   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12984
12985   nextic = ic->next;
12986   if(!nextic)
12987     return 0;
12988
12989   nextright = IC_RIGHT(nextic);
12990   nextleft  = IC_LEFT(nextic);
12991   nextresult = IC_RESULT(nextic);
12992
12993   pic16_aopOp(right,ic,FALSE);
12994   pic16_aopOp(result,ic,FALSE);
12995   pic16_aopOp(nextright,  nextic, FALSE);
12996   pic16_aopOp(nextleft,   nextic, FALSE);
12997   pic16_aopOp(nextresult, nextic, FALSE);
12998
12999   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13000
13001     operand *t = right;
13002     right = nextright;
13003     nextright = t; 
13004
13005     pic16_emitcode(";remove right +","");
13006
13007   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13008 /*
13009     operand *t = right;
13010     right = nextleft;
13011     nextleft = t; 
13012 */
13013     pic16_emitcode(";remove left +","");
13014   } else
13015     return 0;
13016
13017   big = AOP_SIZE(nextleft);
13018   small = AOP_SIZE(nextright);
13019
13020   switch(nextic->op) {
13021
13022   case '+':
13023     pic16_emitcode(";optimize a +","");
13024     /* if unsigned or not an integral type */
13025     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13026       pic16_emitcode(";add a bit to something","");
13027     } else {
13028
13029       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13030
13031       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13032         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13033         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13034       } else
13035         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13036
13037       offset = 0;
13038       while(--big) {
13039
13040         offset++;
13041
13042         if(--small) {
13043           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13044             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13045             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13046           }
13047
13048           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13049           emitSKPNC;
13050           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13051                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13052                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13053           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13054           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13055
13056         } else {
13057           pic16_emitcode("rlf","known_zero,w");
13058
13059           /*
13060             if right is signed
13061               btfsc  right,7
13062                addlw ff
13063           */
13064           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13065             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13066             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13067           } else {
13068             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13069           }
13070         }
13071       }
13072       ret = 1;
13073     }
13074   }
13075   ret = 1;
13076
13077 release:
13078   pic16_freeAsmop(right,NULL,ic,TRUE);
13079   pic16_freeAsmop(result,NULL,ic,TRUE);
13080   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13081   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13082   if(ret)
13083     nextic->generated = 1;
13084
13085   return ret;
13086 #else
13087   return 0;
13088 #endif
13089 }
13090 /*-----------------------------------------------------------------*/
13091 /* genCast - gen code for casting                                  */
13092 /*-----------------------------------------------------------------*/
13093 static void genCast (iCode *ic)
13094 {
13095   operand *result = IC_RESULT(ic);
13096   sym_link *ctype = operandType(IC_LEFT(ic));
13097   sym_link *rtype = operandType(IC_RIGHT(ic));
13098   sym_link *restype = operandType(IC_RESULT(ic));
13099   operand *right = IC_RIGHT(ic);
13100   int size, offset ;
13101
13102
13103     FENTRY;
13104
13105         /* if they are equivalent then do nothing */
13106 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13107 //              return ;
13108
13109         pic16_aopOp(right,ic,FALSE) ;
13110         pic16_aopOp(result,ic,FALSE);
13111
13112         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13113
13114
13115         /* if the result is a bit */
13116         if (AOP_TYPE(result) == AOP_CRY) {
13117         
13118                 /* if the right size is a literal then
13119                  * we know what the value is */
13120                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13121
13122                 if (AOP_TYPE(right) == AOP_LIT) {
13123                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13124                                 pic16_popGet(AOP(result),0));
13125
13126                         if (((int) operandLitValue(right))) 
13127                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13128                                         AOP(result)->aopu.aop_dir,
13129                                         AOP(result)->aopu.aop_dir);
13130                         else
13131                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13132                                         AOP(result)->aopu.aop_dir,
13133                                         AOP(result)->aopu.aop_dir);
13134                         goto release;
13135                 }
13136
13137                 /* the right is also a bit variable */
13138                 if (AOP_TYPE(right) == AOP_CRY) {
13139                         emitCLRC;
13140                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13141
13142                         pic16_emitcode("clrc","");
13143                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13144                                 AOP(right)->aopu.aop_dir,
13145                                 AOP(right)->aopu.aop_dir);
13146                         pic16_aopPut(AOP(result),"c",0);
13147                         goto release ;
13148                 }
13149
13150                 /* we need to or */
13151                 if (AOP_TYPE(right) == AOP_REG) {
13152                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13153                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13154                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13155                 }
13156                 pic16_toBoolean(right);
13157                 pic16_aopPut(AOP(result),"a",0);
13158                 goto release ;
13159         }
13160
13161         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13162           int offset = 1;
13163
13164                 size = AOP_SIZE(result);
13165
13166                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13167
13168                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13169                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13170                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13171
13172                 while (size--)
13173                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13174
13175                 goto release;
13176         }
13177
13178         if(IS_BITFIELD(getSpec(restype))
13179           && IS_BITFIELD(getSpec(rtype))) {
13180           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13181         }
13182
13183         /* if they are the same size : or less */
13184         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13185
13186                 /* if they are in the same place */
13187                 if (pic16_sameRegs(AOP(right),AOP(result)))
13188                         goto release;
13189
13190                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13191 #if 0
13192                 if (IS_PTR_CONST(rtype))
13193 #else
13194                 if (IS_CODEPTR(rtype))
13195 #endif
13196                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13197
13198 #if 0
13199                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13200 #else
13201                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13202 #endif
13203                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13204
13205 #if 0
13206                 if(AOP_TYPE(right) == AOP_IMMD) {
13207                   pCodeOp *pcop0, *pcop1, *pcop2;
13208                   symbol *sym = OP_SYMBOL( right );
13209
13210                         size = AOP_SIZE(result);
13211                         /* low */
13212                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13213                         /* high */
13214                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13215                         /* upper */
13216                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13217         
13218                         if (size == 3) {
13219                                 pic16_emitpcode(POC_MOVLW, pcop0);
13220                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13221                                 pic16_emitpcode(POC_MOVLW, pcop1);
13222                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13223                                 pic16_emitpcode(POC_MOVLW, pcop2);
13224                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13225                         } else
13226                         if (size == 2) {
13227                                 pic16_emitpcode(POC_MOVLW, pcop0);
13228                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13229                                 pic16_emitpcode(POC_MOVLW, pcop1);
13230                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13231                         } else {
13232                                 pic16_emitpcode(POC_MOVLW, pcop0);
13233                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13234                         }
13235                 } else
13236 #endif
13237                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13238                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13239                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13240                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13241                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13242                         if(AOP_SIZE(result) <2)
13243                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13244                 } else {
13245                         /* if they in different places then copy */
13246                         size = AOP_SIZE(result);
13247                         offset = 0 ;
13248                         while (size--) {
13249                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13250                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13251                                 offset++;
13252                         }
13253                 }
13254                 goto release;
13255         }
13256
13257         /* if the result is of type pointer */
13258         if (IS_PTR(ctype)) {
13259           int p_type;
13260           sym_link *type = operandType(right);
13261           sym_link *etype = getSpec(type);
13262
13263                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13264
13265                 /* pointer to generic pointer */
13266                 if (IS_GENPTR(ctype)) {
13267                   char *l = zero;
13268             
13269                         if (IS_PTR(type)) 
13270                                 p_type = DCL_TYPE(type);
13271                         else {
13272                 /* we have to go by the storage class */
13273                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13274
13275 /*              if (SPEC_OCLS(etype)->codesp )  */
13276 /*                  p_type = CPOINTER ;  */
13277 /*              else */
13278 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13279 /*                      p_type = FPOINTER ; */
13280 /*                  else */
13281 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13282 /*                          p_type = PPOINTER; */
13283 /*                      else */
13284 /*                          if (SPEC_OCLS(etype) == idata ) */
13285 /*                              p_type = IPOINTER ; */
13286 /*                          else */
13287 /*                              p_type = POINTER ; */
13288             }
13289                 
13290             /* the first two bytes are known */
13291       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13292             size = GPTRSIZE - 1; 
13293             offset = 0 ;
13294             while (size--) {
13295               if(offset < AOP_SIZE(right)) {
13296                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13297                 mov2f(AOP(result), AOP(right), offset);
13298 /*
13299                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13300                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13301                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13302                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13303                 } else { 
13304                   
13305                   pic16_aopPut(AOP(result),
13306                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13307                          offset);
13308                 }
13309 */
13310               } else 
13311                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13312               offset++;
13313             }
13314             /* the last byte depending on type */
13315             switch (p_type) {
13316             case IPOINTER:
13317             case POINTER:
13318                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13319                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13320 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13321                 break;
13322
13323             case CPOINTER:
13324                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13325                 break;
13326
13327             case FPOINTER:
13328               pic16_emitcode(";BUG!? ","%d",__LINE__);
13329                 l = one;
13330                 break;
13331             case PPOINTER:
13332               pic16_emitcode(";BUG!? ","%d",__LINE__);
13333                 l = "#0x03";
13334                 break;
13335
13336             case GPOINTER:
13337                 if (GPTRSIZE > AOP_SIZE(right)) {
13338                   // assume data pointer... THIS MIGHT BE WRONG!
13339                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13340                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13341                 } else {
13342                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13343                 }
13344               break;
13345               
13346             default:
13347                 /* this should never happen */
13348                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13349                        "got unknown pointer type");
13350                 exit(1);
13351             }
13352             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13353             goto release ;
13354         }
13355         
13356         /* just copy the pointers */
13357         size = AOP_SIZE(result);
13358         offset = 0 ;
13359         while (size--) {
13360             pic16_aopPut(AOP(result),
13361                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13362                    offset);
13363             offset++;
13364         }
13365         goto release ;
13366     }
13367     
13368
13369
13370     /* so we now know that the size of destination is greater
13371     than the size of the source.
13372     Now, if the next iCode is an operator then we might be
13373     able to optimize the operation without performing a cast.
13374     */
13375     if(genMixedOperation(ic))
13376       goto release;
13377
13378     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13379     
13380     /* we move to result for the size of source */
13381     size = AOP_SIZE(right);
13382     offset = 0 ;
13383     while (size--) {
13384       mov2f(AOP(result), AOP(right), offset);
13385       offset++;
13386     }
13387
13388     /* now depending on the sign of the destination */
13389     size = AOP_SIZE(result) - AOP_SIZE(right);
13390     /* if unsigned or not an integral type */
13391     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13392       while (size--)
13393         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13394     } else {
13395       /* we need to extend the sign :( */
13396
13397       if(size == 1) {
13398         /* Save one instruction of casting char to int */
13399         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13400         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13401         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13402       } else {
13403         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13404
13405         if(offset)
13406           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13407         else
13408           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13409         
13410         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13411
13412         while (size--)
13413           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13414       }
13415     }
13416
13417 release:
13418     pic16_freeAsmop(right,NULL,ic,TRUE);
13419     pic16_freeAsmop(result,NULL,ic,TRUE);
13420
13421 }
13422
13423 /*-----------------------------------------------------------------*/
13424 /* genDjnz - generate decrement & jump if not zero instrucion      */
13425 /*-----------------------------------------------------------------*/
13426 static int genDjnz (iCode *ic, iCode *ifx)
13427 {
13428     symbol *lbl, *lbl1;
13429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13430
13431     if (!ifx)
13432         return 0;
13433     
13434     /* if the if condition has a false label
13435        then we cannot save */
13436     if (IC_FALSE(ifx))
13437         return 0;
13438
13439     /* if the minus is not of the form 
13440        a = a - 1 */
13441     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13442         !IS_OP_LITERAL(IC_RIGHT(ic)))
13443         return 0;
13444
13445     if (operandLitValue(IC_RIGHT(ic)) != 1)
13446         return 0;
13447
13448     /* if the size of this greater than one then no
13449        saving */
13450     if (getSize(operandType(IC_RESULT(ic))) > 1)
13451         return 0;
13452
13453     /* otherwise we can save BIG */
13454     lbl = newiTempLabel(NULL);
13455     lbl1= newiTempLabel(NULL);
13456
13457     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13458     
13459     if (IS_AOP_PREG(IC_RESULT(ic))) {
13460         pic16_emitcode("dec","%s",
13461                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13462         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13463         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13464     } else {    
13465
13466
13467       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13468       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13469
13470       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13471       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13472
13473     }
13474     
13475     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13476     ifx->generated = 1;
13477     return 1;
13478 }
13479
13480 /*-----------------------------------------------------------------*/
13481 /* genReceive - generate code for a receive iCode                  */
13482 /*-----------------------------------------------------------------*/
13483 static void genReceive (iCode *ic)
13484 {    
13485
13486   FENTRY;
13487
13488 #if 0
13489   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13490         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13491 #endif
13492 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13493
13494   if (isOperandInFarSpace(IC_RESULT(ic))
13495       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13496           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13497
13498     int size = getSize(operandType(IC_RESULT(ic)));
13499     int offset =  pic16_fReturnSizePic - size;
13500
13501       assert( 0 );
13502       while (size--) {
13503         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13504                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13505                       offset++;
13506         }
13507
13508       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13509
13510       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13511       size = AOP_SIZE(IC_RESULT(ic));
13512       offset = 0;
13513       while (size--) {
13514         pic16_emitcode ("pop","acc");
13515         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13516       }
13517   } else {
13518     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13519     _G.accInUse++;
13520     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13521     _G.accInUse--;
13522
13523     /* set pseudo stack pointer to where it should be - dw*/
13524     GpsuedoStkPtr = ic->parmBytes;
13525
13526     /* setting GpsuedoStkPtr has side effects here: */
13527     assignResultValue(IC_RESULT(ic), 0);
13528   }
13529
13530   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13531 }
13532
13533 /*-----------------------------------------------------------------*/
13534 /* genDummyRead - generate code for dummy read of volatiles        */
13535 /*-----------------------------------------------------------------*/
13536 static void
13537 genDummyRead (iCode * ic)
13538 {
13539   pic16_emitcode ("; genDummyRead","");
13540   pic16_emitcode ("; not implemented","");
13541
13542   ic = ic;
13543 }
13544
13545 /*-----------------------------------------------------------------*/
13546 /* genpic16Code - generate code for pic16 based controllers        */
13547 /*-----------------------------------------------------------------*/
13548 /*
13549  * At this point, ralloc.c has gone through the iCode and attempted
13550  * to optimize in a way suitable for a PIC. Now we've got to generate
13551  * PIC instructions that correspond to the iCode.
13552  *
13553  * Once the instructions are generated, we'll pass through both the
13554  * peep hole optimizer and the pCode optimizer.
13555  *-----------------------------------------------------------------*/
13556
13557 void genpic16Code (iCode *lic)
13558 {
13559   iCode *ic;
13560   int cln = 0;
13561
13562     lineHead = lineCurr = NULL;
13563
13564     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13565     pic16_addpBlock(pb);
13566
13567 #if 0
13568     /* if debug information required */
13569     if (options.debug && currFunc) {
13570       if (currFunc) {
13571         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13572       }
13573     }
13574 #endif
13575
13576     for (ic = lic ; ic ; ic = ic->next ) {
13577
13578       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13579       if ( cln != ic->lineno ) {
13580         if ( options.debug ) {
13581           debugFile->writeCLine (ic);
13582         }
13583         
13584         if(!options.noCcodeInAsm) {
13585           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13586               printCLine(ic->filename, ic->lineno)));
13587         }
13588
13589         cln = ic->lineno ;
13590       }
13591         
13592       if(options.iCodeInAsm) {
13593         char *l;
13594
13595           /* insert here code to print iCode as comment */
13596           l = Safe_strdup(printILine(ic));
13597           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13598       }
13599         
13600       /* if the result is marked as
13601        * spilt and rematerializable or code for
13602        * this has already been generated then
13603        * do nothing */
13604       if (resultRemat(ic) || ic->generated ) 
13605         continue ;
13606         
13607       /* depending on the operation */
13608       switch (ic->op) {
13609         case '!' :
13610           pic16_genNot(ic);
13611           break;
13612             
13613         case '~' :
13614           pic16_genCpl(ic);
13615           break;
13616             
13617         case UNARYMINUS:
13618           genUminus (ic);
13619           break;
13620             
13621         case IPUSH:
13622           genIpush (ic);
13623           break;
13624             
13625         case IPOP:
13626           /* IPOP happens only when trying to restore a 
13627            * spilt live range, if there is an ifx statement
13628            * following this pop then the if statement might
13629            * be using some of the registers being popped which
13630            * would destroy the contents of the register so
13631            * we need to check for this condition and handle it */
13632            if (ic->next
13633              && ic->next->op == IFX
13634              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13635                genIfx (ic->next,ic);
13636           else
13637             genIpop (ic);
13638           break; 
13639             
13640         case CALL:
13641           genCall (ic);
13642           break;
13643             
13644         case PCALL:
13645           genPcall (ic);
13646           break;
13647             
13648         case FUNCTION:
13649           genFunction (ic);
13650           break;
13651             
13652         case ENDFUNCTION:
13653           genEndFunction (ic);
13654           break;
13655             
13656         case RETURN:
13657           genRet (ic);
13658           break;
13659             
13660         case LABEL:
13661           genLabel (ic);
13662           break;
13663             
13664         case GOTO:
13665           genGoto (ic);
13666           break;
13667             
13668         case '+' :
13669           pic16_genPlus (ic) ;
13670           break;
13671             
13672         case '-' :
13673           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13674             pic16_genMinus (ic);
13675           break;
13676
13677         case '*' :
13678           genMult (ic);
13679           break;
13680             
13681         case '/' :
13682           genDiv (ic) ;
13683           break;
13684             
13685         case '%' :
13686           genMod (ic);
13687           break;
13688             
13689         case '>' :
13690           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13691           break;
13692             
13693         case '<' :
13694           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13695           break;
13696             
13697         case LE_OP:
13698         case GE_OP:
13699         case NE_OP:
13700           /* note these two are xlated by algebraic equivalence
13701            * during parsing SDCC.y */
13702           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13703             "got '>=' or '<=' shouldn't have come here");
13704           break;
13705
13706         case EQ_OP:
13707           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13708           break;            
13709             
13710         case AND_OP:
13711           genAndOp (ic);
13712           break;
13713             
13714         case OR_OP:
13715           genOrOp (ic);
13716           break;
13717             
13718         case '^' :
13719           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13720           break;
13721             
13722         case '|' :
13723           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13724           break;
13725             
13726         case BITWISEAND:
13727           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13728           break;
13729             
13730         case INLINEASM:
13731           genInline (ic);
13732           break;
13733             
13734         case RRC:
13735           genRRC (ic);
13736           break;
13737             
13738         case RLC:
13739           genRLC (ic);
13740           break;
13741             
13742         case GETHBIT:
13743           genGetHbit (ic);
13744           break;
13745             
13746         case LEFT_OP:
13747           genLeftShift (ic);
13748           break;
13749             
13750         case RIGHT_OP:
13751           genRightShift (ic);
13752           break;
13753             
13754         case GET_VALUE_AT_ADDRESS:
13755           genPointerGet(ic);
13756           break;
13757             
13758         case '=' :
13759           if (POINTER_SET(ic))
13760             genPointerSet(ic);
13761           else
13762             genAssign(ic);
13763           break;
13764             
13765         case IFX:
13766           genIfx (ic,NULL);
13767           break;
13768             
13769         case ADDRESS_OF:
13770           genAddrOf (ic);
13771           break;
13772             
13773         case JUMPTABLE:
13774           genJumpTab (ic);
13775           break;
13776             
13777         case CAST:
13778           genCast (ic);
13779           break;
13780             
13781         case RECEIVE:
13782           genReceive(ic);
13783           break;
13784             
13785         case SEND:
13786           addSet(&_G.sendSet,ic);
13787           break;
13788
13789         case DUMMY_READ_VOLATILE:
13790           genDummyRead (ic);
13791           break;
13792
13793         default :
13794           ic = ic;
13795       }
13796     }
13797
13798
13799     /* now we are ready to call the
13800        peep hole optimizer */
13801     if (!options.nopeep)
13802       peepHole (&lineHead);
13803
13804     /* now do the actual printing */
13805     printLine (lineHead, codeOutFile);
13806
13807 #ifdef PCODE_DEBUG
13808     DFPRINTF((stderr,"printing pBlock\n\n"));
13809     pic16_printpBlock(stdout,pb);
13810 #endif
13811
13812     return;
13813 }
13814