]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
bc7aed3efeed171bc697901fffdcaa6df83cbcd1
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 /* 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 #if 1
652     /* assign depending on the storage class */
653     /* if it is on the stack or indirectly addressable */
654     /* space we need to assign either r0 or r1 to it   */    
655     if (sym->onStack || sym->iaccess) {
656       pCodeOp *pcop[4];
657       int i;
658       
659         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
660                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
661         
662         /* acquire a temporary register -- it is saved in function */
663
664         sym->aop = aop = newAsmop(AOP_STA);
665         aop->aopu.stk.stk = sym->stack;
666         aop->size = getSize(sym->type);
667
668
669         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
670         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
671           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
672           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
673           
674           for(i=0;i<aop->size;i++)
675             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
676             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
677         } else
678           for(i=0;i<aop->size;i++) {
679             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
680             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
681           }
682
683
684 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
685
686 #if 1
687         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
688         
689         if(_G.accInUse) {
690                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
691         }
692         
693         for(i=0;i<aop->size;i++) {
694
695           /* initialise for stack access via frame pointer */
696           // operands on stack are accessible via "FSR2 + index" with index
697           // starting at 2 for arguments and growing from 0 downwards for
698           // local variables (index == 0 is not assigned so we add one here)
699           {
700             int soffs = sym->stack;
701             if (soffs <= 0) {
702               assert (soffs < 0);
703               soffs++;
704             } // if
705             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
706             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
707                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
708           }
709         }
710         
711         if(_G.accInUse) {
712                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
713         }
714         
715         return (aop);
716 #endif
717
718 #if 0
719         /* now assign the address of the variable to 
720         the pointer register */
721         if (aop->type != AOP_STK) {
722
723             if (sym->onStack) {
724                     if ( _G.accInUse )
725                         pic16_emitcode("push","acc");
726
727                     pic16_emitcode("mov","a,_bp");
728                     pic16_emitcode("add","a,#0x%02x",
729                              ((sym->stack < 0) ?
730                               ((char)(sym->stack - _G.nRegsSaved )) :
731                               ((char)sym->stack)) & 0xff);
732                     pic16_emitcode("mov","%s,a",
733                              aop->aopu.aop_ptr->name);
734
735                     if ( _G.accInUse )
736                         pic16_emitcode("pop","acc");
737             } else
738                 pic16_emitcode("mov","%s,#%s",
739                          aop->aopu.aop_ptr->name,
740                          sym->rname);
741             aop->paged = space->paged;
742         } else
743             aop->aopu.aop_stk = sym->stack;
744         return aop;
745 #endif
746
747     }
748 #endif
749
750 #if 0
751     if (sym->onStack && options.stack10bit)
752     {
753         /* It's on the 10 bit stack, which is located in
754          * far data space.
755          */
756          
757       //DEBUGpic16_emitcode(";","%d",__LINE__);
758
759         if ( _G.accInUse )
760                 pic16_emitcode("push","acc");
761
762         pic16_emitcode("mov","a,_bp");
763         pic16_emitcode("add","a,#0x%02x",
764                  ((sym->stack < 0) ?
765                    ((char)(sym->stack - _G.nRegsSaved )) :
766                    ((char)sym->stack)) & 0xff);
767         
768         genSetDPTR(1);
769         pic16_emitcode ("mov","dpx1,#0x40");
770         pic16_emitcode ("mov","dph1,#0x00");
771         pic16_emitcode ("mov","dpl1, a");
772         genSetDPTR(0);
773         
774         if ( _G.accInUse )
775             pic16_emitcode("pop","acc");
776             
777         sym->aop = aop = newAsmop(AOP_DPTR2);
778         aop->size = getSize(sym->type); 
779         return aop;
780     }
781 #endif
782
783 #if 0
784     /* special case for a function */
785     if (IS_FUNC(sym->type)) {   
786         sym->aop = aop = newAsmop(AOP_PCODE);
787         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
788         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790         PCOI(aop->aopu.pcop)->index = 0;
791         aop->size = FPTRSIZE; 
792         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
793         return aop;
794     }
795 #endif
796
797
798
799     //DEBUGpic16_emitcode(";","%d",__LINE__);
800     /* if in bit space */
801     if (IN_BITSPACE(space)) {
802         sym->aop = aop = newAsmop (AOP_CRY);
803         aop->aopu.aop_dir = sym->rname ;
804         aop->size = getSize(sym->type);
805         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
806         return aop;
807     }
808     /* if it is in direct space */
809     if (IN_DIRSPACE(space)) {
810         sym->aop = aop = newAsmop (AOP_DIR);
811         aop->aopu.aop_dir = sym->rname ;
812         aop->size = getSize(sym->type);
813         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
814         pic16_allocDirReg( IC_LEFT(ic) );
815         return aop;
816     }
817
818
819     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
820         sym->aop = aop = newAsmop (AOP_DIR);
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         pic16_allocDirReg( IC_LEFT(ic) );
825         return aop;
826     }
827
828
829     /* only remaining is far space */
830     sym->aop = aop = newAsmop(AOP_PCODE);
831
832 /* change the next if to 1 to revert to good old immediate code */
833         if(IN_CODESPACE(space)) {
834                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
835                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
836                 PCOI(aop->aopu.pcop)->index = 0;
837         } else {
838                 /* try to allocate via direct register */
839                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
840 //              aop->size = getSize( sym->type );
841         }
842
843         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
844                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
845
846 #if 0
847         if(!pic16_allocDirReg (IC_LEFT(ic)))
848                 return NULL;
849 #endif
850
851         if(IN_DIRSPACE( space ))
852                 aop->size = PTRSIZE;
853         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
854                 aop->size = FPTRSIZE;
855         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
856         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
857         else if(sym->onStack) {
858                 aop->size = PTRSIZE;
859         } else {
860                 assert( 0 );
861         }
862
863     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
864
865     /* if it is in code space */
866     if (IN_CODESPACE(space))
867         aop->code = 1;
868
869     return aop;     
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* aopForRemat - rematerialzes an object                           */
874 /*-----------------------------------------------------------------*/
875 static asmop *aopForRemat (operand *op) // x symbol *sym)
876 {
877   symbol *sym = OP_SYMBOL(op);
878   operand *refop;
879   iCode *ic = NULL, *oldic;
880   asmop *aop = newAsmop(AOP_PCODE);
881   int val = 0;
882   int offset = 0;
883   int viaimmd=0;
884
885     FENTRY2;
886     
887         ic = sym->rematiCode;
888
889         if(IS_OP_POINTER(op)) {
890                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
891         }
892
893         for (;;) {
894                 oldic = ic;
895
896 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
897         
898                 if (ic->op == '+') {
899                         val += (int) operandLitValue(IC_RIGHT(ic));
900                 } else if (ic->op == '-') {
901                         val -= (int) operandLitValue(IC_RIGHT(ic));
902                 } else
903                         break;
904                 
905                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
906         }
907
908         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
909         refop = IC_LEFT(ic);
910
911         if(!op->isaddr)viaimmd++; else viaimmd=0;
912                 
913 /* set the following if to 1 to revert to good old immediate code */
914         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
915                 || viaimmd) {
916
917                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
918
919                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
920
921 #if 0
922                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
923 #else
924                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
925 #endif
926
927                 PCOI(aop->aopu.pcop)->index = val;
928                 
929                 aop->size = getSize( sym->type );
930         } else {
931                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
932
933                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
934                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
935
936                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
937         }
938
939
940         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
941                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
942 #if 0
943                 val, IS_PTR_CONST(operandType(op)));
944 #else
945                 val, IS_CODEPTR(operandType(op)));
946 #endif
947
948 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
949
950         pic16_allocDirReg (IC_LEFT(ic));
951
952         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
953                 aop->code = 1;
954
955   return aop;        
956 }
957
958 #if 0
959 static int aopIdx (asmop *aop, int offset)
960 {
961   if(!aop)
962     return -1;
963
964   if(aop->type !=  AOP_REG)
965     return -2;
966         
967   return aop->aopu.aop_reg[offset]->rIdx;
968
969 }
970 #endif
971
972 /*-----------------------------------------------------------------*/
973 /* regsInCommon - two operands have some registers in common       */
974 /*-----------------------------------------------------------------*/
975 static bool regsInCommon (operand *op1, operand *op2)
976 {
977     symbol *sym1, *sym2;
978     int i;
979
980     /* if they have registers in common */
981     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
982         return FALSE ;
983
984     sym1 = OP_SYMBOL(op1);
985     sym2 = OP_SYMBOL(op2);
986
987     if (sym1->nRegs == 0 || sym2->nRegs == 0)
988         return FALSE ;
989
990     for (i = 0 ; i < sym1->nRegs ; i++) {
991         int j;
992         if (!sym1->regs[i])
993             continue ;
994
995         for (j = 0 ; j < sym2->nRegs ;j++ ) {
996             if (!sym2->regs[j])
997                 continue ;
998
999             if (sym2->regs[j] == sym1->regs[i])
1000                 return TRUE ;
1001         }
1002     }
1003
1004     return FALSE ;
1005 }
1006
1007 /*-----------------------------------------------------------------*/
1008 /* operandsEqu - equivalent                                        */
1009 /*-----------------------------------------------------------------*/
1010 static bool operandsEqu ( operand *op1, operand *op2)
1011 {
1012     symbol *sym1, *sym2;
1013
1014     /* if they not symbols */
1015     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1016         return FALSE;
1017
1018     sym1 = OP_SYMBOL(op1);
1019     sym2 = OP_SYMBOL(op2);
1020
1021     /* if both are itemps & one is spilt
1022        and the other is not then false */
1023     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1024         sym1->isspilt != sym2->isspilt )
1025         return FALSE ;
1026
1027     /* if they are the same */
1028     if (sym1 == sym2)
1029         return TRUE ;
1030
1031     if (sym1->rname[0] && sym2->rname[0]
1032         && strcmp (sym1->rname, sym2->rname) == 0)
1033         return TRUE;
1034
1035
1036     /* if left is a tmp & right is not */
1037     if (IS_ITEMP(op1)  && 
1038         !IS_ITEMP(op2) &&
1039         sym1->isspilt  &&
1040         (sym1->usl.spillLoc == sym2))
1041         return TRUE;
1042
1043     if (IS_ITEMP(op2)  && 
1044         !IS_ITEMP(op1) &&
1045         sym2->isspilt  &&
1046         sym1->level > 0 &&
1047         (sym2->usl.spillLoc == sym1))
1048         return TRUE ;
1049
1050     return FALSE ;
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_sameRegs - two asmops have the same registers                   */
1055 /*-----------------------------------------------------------------*/
1056 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1057 {
1058     int i;
1059
1060     if (aop1 == aop2)
1061         return TRUE ;
1062
1063     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1064                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1065
1066     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1067
1068     if (aop1->type != AOP_REG ||
1069         aop2->type != AOP_REG )
1070         return FALSE ;
1071
1072     if (aop1->size != aop2->size )
1073         return FALSE ;
1074
1075     for (i = 0 ; i < aop1->size ; i++ ) {
1076 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1077
1078 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1079         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1080             return FALSE ;
1081     }
1082
1083     return TRUE ;
1084 }
1085
1086 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1087 {
1088     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1089                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1090
1091     if(aop1 == aop2)return TRUE;
1092     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1093       
1094       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1095     
1096   return TRUE;
1097 }
1098
1099
1100 /*-----------------------------------------------------------------*/
1101 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1102 /*-----------------------------------------------------------------*/
1103 void pic16_aopOp (operand *op, iCode *ic, bool result)
1104 {
1105     asmop *aop;
1106     symbol *sym;
1107     int i;
1108
1109     if (!op)
1110         return ;
1111
1112     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1113
1114     /* if this a literal */
1115     if (IS_OP_LITERAL(op)) {
1116         op->aop = aop = newAsmop(AOP_LIT);
1117         aop->aopu.aop_lit = op->operand.valOperand;
1118         aop->size = getSize(operandType(op));
1119         return;
1120     }
1121
1122     {
1123       sym_link *type = operandType(op);
1124 #if 0
1125       if(IS_PTR_CONST(type))
1126 #else
1127       if(IS_CODEPTR(type))
1128 #endif
1129         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1130     }
1131
1132     /* if already has a asmop then continue */
1133     if (op->aop)
1134         return ;
1135
1136     /* if the underlying symbol has a aop */
1137     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1138       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1139         op->aop = OP_SYMBOL(op)->aop;
1140         return;
1141     }
1142
1143     /* if this is a true symbol */
1144     if (IS_TRUE_SYMOP(op)) {    
1145         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1146       op->aop = aopForSym(ic, op, result);
1147       return ;
1148     }
1149
1150     /* this is a temporary : this has
1151     only four choices :
1152     a) register
1153     b) spillocation
1154     c) rematerialize 
1155     d) conditional   
1156     e) can be a return use only */
1157
1158     sym = OP_SYMBOL(op);
1159
1160     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1161     /* if the type is a conditional */
1162     if (sym->regType == REG_CND) {
1163         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1164         aop->size = 0;
1165         return;
1166     }
1167
1168     /* if it is spilt then two situations
1169     a) is rematerialize 
1170     b) has a spill location */
1171     if (sym->isspilt || sym->nRegs == 0) {
1172
1173       DEBUGpic16_emitcode(";","%d",__LINE__);
1174         /* rematerialize it NOW */
1175         if (sym->remat) {
1176
1177             sym->aop = op->aop = aop = aopForRemat (op);
1178 //            aop->size = getSize(sym->type);
1179 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1180             return;
1181         }
1182
1183 #if 1
1184         if (sym->accuse) {
1185             int i;
1186             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1187             aop->size = getSize(sym->type);
1188             for ( i = 0 ; i < 1 ; i++ ) {
1189                 aop->aopu.aop_str[i] = accUse[i];
1190 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1191             }
1192             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1193             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1194             return;  
1195         }
1196 #endif
1197
1198 #if 1
1199         if (sym->ruonly ) {
1200           /*
1201           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1202           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1203           //pic16_allocDirReg (IC_LEFT(ic));
1204           aop->size = getSize(sym->type);
1205           */
1206
1207           unsigned i;
1208
1209           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1210           aop->size = getSize(sym->type);
1211           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1212             aop->aopu.aop_str[i] = fReturn[i];
1213
1214           DEBUGpic16_emitcode(";","%d",__LINE__);
1215           return;
1216         }
1217 #endif
1218         /* else spill location  */
1219         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1220             /* force a new aop if sizes differ */
1221             sym->usl.spillLoc->aop = NULL;
1222         }
1223
1224 #if 0
1225         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1226                             __FUNCTION__,__LINE__,
1227                             sym->usl.spillLoc->rname,
1228                             sym->rname, sym->usl.spillLoc->offset);
1229 #endif
1230
1231         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1232         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1233         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1234                                           getSize(sym->type), 
1235                                           sym->usl.spillLoc->offset, op);
1236         aop->size = getSize(sym->type);
1237
1238         return;
1239     }
1240
1241     {
1242       sym_link *type = operandType(op);
1243 #if 0
1244       if(IS_PTR_CONST(type)) 
1245 #else
1246       if(IS_CODEPTR(type)) 
1247 #endif
1248         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1249     }
1250
1251     /* must be in a register */
1252     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1253     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1254     aop->size = sym->nRegs;
1255     for ( i = 0 ; i < sym->nRegs ;i++)
1256         aop->aopu.aop_reg[i] = sym->regs[i];
1257 }
1258
1259 /*-----------------------------------------------------------------*/
1260 /* pic16_freeAsmop - free up the asmop given to an operand               */
1261 /*----------------------------------------------------------------*/
1262 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1263 {   
1264     asmop *aop ;
1265
1266     if (!op)
1267         aop = aaop;
1268     else 
1269         aop = op->aop;
1270
1271     if (!aop)
1272         return ;
1273
1274     if (aop->freed)
1275         goto dealloc; 
1276
1277     aop->freed = 1;
1278
1279     /* depending on the asmop type only three cases need work AOP_RO
1280        , AOP_R1 && AOP_STK */
1281 #if 1
1282     switch (aop->type) {
1283         case AOP_FSR0 :
1284             if (_G.fsr0Pushed ) {
1285                 if (pop) {
1286                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1287                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1288 //                    pic16_emitcode ("pop","ar0");
1289                     _G.fsr0Pushed--;
1290                 }
1291             }
1292             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1293             break;
1294
1295         case AOP_FSR2 :
1296             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1297             break;
1298
1299         case AOP_R0 :
1300             if (_G.r0Pushed ) {
1301                 if (pop) {
1302                     pic16_emitcode ("pop","ar0");     
1303                     _G.r0Pushed--;
1304                 }
1305             }
1306             bitVectUnSetBit(ic->rUsed,R0_IDX);
1307             break;
1308
1309         case AOP_R1 :
1310             if (_G.r1Pushed ) {
1311                 if (pop) {
1312                     pic16_emitcode ("pop","ar1");
1313                     _G.r1Pushed--;
1314                 }
1315             }
1316             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1317             break;
1318
1319         case AOP_STA:
1320           {
1321             int i;
1322
1323               /* we must store the result on stack */
1324               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1325                 // operands on stack are accessible via "FSR2 + index" with index
1326                 // starting at 2 for arguments and growing from 0 downwards for
1327                 // local variables (index == 0 is not assigned so we add one here)
1328                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1329                 if (soffs <= 0) {
1330                   assert (soffs < 0);
1331                   soffs++;
1332                 } // if
1333                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1334                 for(i=0;i<aop->size;i++) {
1335                   /* initialise for stack access via frame pointer */
1336                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1337                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1338                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1339                 }
1340         
1341                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1342               }
1343
1344               if(!_G.resDirect) {
1345                 for(i=0;i<aop->size;i++)
1346                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1347               }
1348               _G.resDirect = 0;
1349           }
1350           break;
1351 #if 0
1352         case AOP_STK :
1353         {
1354             int sz = aop->size;    
1355             int stk = aop->aopu.aop_stk + aop->size;
1356             bitVectUnSetBit(ic->rUsed,R0_IDX);
1357             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1358
1359             getFreePtr(ic,&aop,FALSE);
1360             
1361             if (options.stack10bit)
1362             {
1363                 /* I'm not sure what to do here yet... */
1364                 /* #STUB */
1365                 fprintf(stderr, 
1366                         "*** Warning: probably generating bad code for "
1367                         "10 bit stack mode.\n");
1368             }
1369             
1370             if (stk) {
1371                 pic16_emitcode ("mov","a,_bp");
1372                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1373                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1374             } else {
1375                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1376             }
1377
1378             while (sz--) {
1379                 pic16_emitcode("pop","acc");
1380                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1381                 if (!sz) break;
1382                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1383             }
1384             op->aop = aop;
1385             pic16_freeAsmop(op,NULL,ic,TRUE);
1386             if (_G.r0Pushed) {
1387                 pic16_emitcode("pop","ar0");
1388                 _G.r0Pushed--;
1389             }
1390
1391             if (_G.r1Pushed) {
1392                 pic16_emitcode("pop","ar1");
1393                 _G.r1Pushed--;
1394             }       
1395         }
1396 #endif
1397
1398     }
1399 #endif
1400
1401 dealloc:
1402     /* all other cases just dealloc */
1403     if (op ) {
1404         op->aop = NULL;
1405         if (IS_SYMOP(op)) {
1406             OP_SYMBOL(op)->aop = NULL;    
1407             /* if the symbol has a spill */
1408             if (SPIL_LOC(op))
1409                 SPIL_LOC(op)->aop = NULL;
1410         }
1411     }
1412 }
1413
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_aopGet - for fetching value of the aop                          */
1416 /*-----------------------------------------------------------------*/
1417 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1418 {
1419     char *s = buffer ;
1420     char *rs;
1421
1422     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1423
1424     /* offset is greater than size then zero */
1425     if (offset > (aop->size - 1) &&
1426         aop->type != AOP_LIT)
1427         return zero;
1428
1429     /* depending on type */
1430     switch (aop->type) {
1431
1432     case AOP_FSR0:
1433     case AOP_FSR2:
1434       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1435       rs = Safe_calloc(1, strlen(s)+1);
1436       strcpy(rs, s);
1437       return (rs);
1438       
1439 #if 0
1440       /* if we need to increment it */
1441       while (offset > aop->coff)
1442         {
1443           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1444           aop->coff++;
1445         }
1446
1447       while (offset < aop->coff)
1448         {
1449           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1450           aop->coff--;
1451         }
1452       aop->coff = offset;
1453       if (aop->paged)
1454         {
1455           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1456           return (dname ? "acc" : "a");
1457         }
1458       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1459       rs = Safe_calloc (1, strlen (s) + 1);
1460       strcpy (rs, s);
1461       return rs;
1462 #endif
1463
1464         
1465     case AOP_IMMD:
1466         if (bit16) 
1467             sprintf (s,"%s",aop->aopu.aop_immd);
1468         else
1469             if (offset) 
1470                 sprintf(s,"(%s >> %d)",
1471                         aop->aopu.aop_immd,
1472                         offset*8);
1473             else
1474                 sprintf(s,"%s",
1475                         aop->aopu.aop_immd);
1476         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1477         rs = Safe_calloc(1,strlen(s)+1);
1478         strcpy(rs,s);   
1479         return rs;
1480         
1481     case AOP_DIR:
1482       if (offset) {
1483         sprintf(s,"(%s + %d)",
1484                 aop->aopu.aop_dir,
1485                 offset);
1486         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1487       } else
1488             sprintf(s,"%s",aop->aopu.aop_dir);
1489         rs = Safe_calloc(1,strlen(s)+1);
1490         strcpy(rs,s);   
1491         return rs;
1492         
1493     case AOP_REG:
1494       //if (dname) 
1495       //    return aop->aopu.aop_reg[offset]->dname;
1496       //else
1497             return aop->aopu.aop_reg[offset]->name;
1498         
1499     case AOP_CRY:
1500       //pic16_emitcode(";","%d",__LINE__);
1501       return aop->aopu.aop_dir;
1502         
1503     case AOP_ACC:
1504         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1505 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1506 //        assert( 0 );
1507 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1508         rs = Safe_strdup("WREG");
1509         return (rs);
1510
1511     case AOP_LIT:
1512         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1513         rs = Safe_calloc(1,strlen(s)+1);
1514         strcpy(rs,s);   
1515         return rs;
1516         
1517     case AOP_STR:
1518         aop->coff = offset ;
1519         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1520             dname)
1521             return "acc";
1522         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1523         
1524         return aop->aopu.aop_str[offset];
1525         
1526     case AOP_PCODE:
1527       {
1528         pCodeOp *pcop = aop->aopu.pcop;
1529         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1530         if(pcop->name) {
1531           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1532           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1533           if (offset) {
1534             sprintf(s,"(%s + %d)", pcop->name, offset);
1535           } else {
1536             sprintf(s,"%s", pcop->name);
1537           }
1538         } else
1539           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1540
1541       }
1542       rs = Safe_calloc(1,strlen(s)+1);
1543       strcpy(rs,s);   
1544       return rs;
1545
1546     case AOP_STA:
1547         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1548         return (rs);
1549         
1550     case AOP_STK:
1551 //        pCodeOp *pcop = aop->aop
1552         break;
1553
1554     }
1555
1556     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1557     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1558            "aopget got unsupported aop->type");
1559     exit(0);
1560 }
1561
1562
1563
1564 /* lock has the following meaning: When allocating temporary registers
1565  * for stack variables storage, the value of the temporary register is
1566  * saved on stack. Its value is restored at the end. This procedure is
1567  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1568  * a possibility that before a call to pic16_aopOp, a temporary register
1569  * is allocated for a while and it is freed after some time, this will
1570  * mess the stack and values will not be restored properly. So use lock=1
1571  * to allocate temporary registers used internally by the programmer, and
1572  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1573  * to inform the compiler developer about a possible bug. This is an internal
1574  * feature for developing the compiler -- VR */
1575  
1576 int _TempReg_lock = 0;
1577 /*-----------------------------------------------------------------*/
1578 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1579 /*-----------------------------------------------------------------*/
1580 pCodeOp *pic16_popGetTempReg(int lock)
1581 {
1582   pCodeOp *pcop;
1583   symbol *cfunc;
1584
1585 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1586     if(_TempReg_lock) {
1587 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1588     }
1589     
1590     _TempReg_lock += lock;
1591     
1592     cfunc = currFunc;
1593     currFunc = NULL;
1594
1595     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1596     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597       PCOR(pcop)->r->wasUsed=1;
1598       PCOR(pcop)->r->isFree=0;
1599
1600       /* push value on stack */
1601       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1602     }
1603
1604     currFunc = cfunc;
1605
1606   return pcop;
1607 }
1608
1609 /*-----------------------------------------------------------------*/
1610 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1611 /*                            don't save if inside v               */
1612 /*-----------------------------------------------------------------*/
1613 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1614 {
1615   pCodeOp *pcop;
1616   symbol *cfunc;
1617
1618 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1619
1620     if(_TempReg_lock) {
1621 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1622     }
1623
1624     _TempReg_lock += lock;
1625
1626     cfunc = currFunc;
1627     currFunc = NULL;
1628
1629     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1630     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1631       PCOR(pcop)->r->wasUsed=1;
1632       PCOR(pcop)->r->isFree=0;
1633
1634       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1635       /* push value on stack */
1636         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1637       }
1638     }
1639
1640     currFunc = cfunc;
1641
1642   return pcop;
1643 }
1644
1645
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1648 /*-----------------------------------------------------------------*/
1649 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1650 {
1651   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1652
1653   _TempReg_lock -= lock;
1654
1655   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1656     PCOR(pcop)->r->isFree = 1;
1657     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1658   }
1659 }
1660 /*-----------------------------------------------------------------*/
1661 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1662 /*-----------------------------------------------------------------*/
1663 pCodeOp *pic16_popGetLabel(unsigned int key)
1664 {
1665
1666   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1667
1668   if(key>max_key)
1669     max_key = key;
1670
1671   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popCopyReg - copy a pcode operator                              */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1678 {
1679   pCodeOpReg *pcor;
1680
1681   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1682   pcor->pcop.type = pc->pcop.type;
1683   if(pc->pcop.name) {
1684     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1685       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1686   } else
1687     pcor->pcop.name = NULL;
1688
1689   pcor->r = pc->r;
1690   pcor->rIdx = pc->rIdx;
1691   pcor->r->wasUsed=1;
1692   pcor->instance = pc->instance;
1693
1694 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1695
1696   return PCOP(pcor);
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1701 /*-----------------------------------------------------------------*/
1702 pCodeOp *pic16_popGetLit(int lit)
1703 {
1704   return pic16_newpCodeOpLit(lit);
1705 }
1706
1707 /*-----------------------------------------------------------------*/
1708 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1709 /*-----------------------------------------------------------------*/
1710 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1711 {
1712   return pic16_newpCodeOpLit2(lit, arg2);
1713 }
1714
1715
1716 /*-----------------------------------------------------------------*/
1717 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1718 /*-----------------------------------------------------------------*/
1719 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1720 {
1721   return pic16_newpCodeOpImmd(name, offset,index, 0);
1722 }
1723
1724
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGet - asm operator to pcode operator conversion              */
1727 /*-----------------------------------------------------------------*/
1728 pCodeOp *pic16_popGetWithString(char *str)
1729 {
1730   pCodeOp *pcop;
1731
1732
1733   if(!str) {
1734     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1735     exit (1);
1736   }
1737
1738   pcop = pic16_newpCodeOp(str,PO_STR);
1739
1740   return pcop;
1741 }
1742
1743 /*-----------------------------------------------------------------*/
1744 /* pic16_popRegFromString -                                        */
1745 /*-----------------------------------------------------------------*/
1746 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1747 {
1748
1749   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1750   pcop->type = PO_DIR;
1751
1752   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1753   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1754
1755   if(!str)
1756     str = "BAD_STRING";
1757
1758   pcop->name = Safe_calloc(1,strlen(str)+1);
1759   strcpy(pcop->name,str);
1760
1761   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1762
1763   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1764
1765   /* make sure that register doesn't exist,
1766    * and operand isn't NULL
1767    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1768   if((PCOR(pcop)->r == NULL) 
1769     && (op)
1770     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1771 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1772 //              __FUNCTION__, __LINE__, str, size, offset);
1773
1774     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1775     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1776
1777   }
1778   PCOR(pcop)->instance = offset;
1779
1780   return pcop;
1781 }
1782
1783 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1784 {
1785   pCodeOp *pcop;
1786
1787 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1788
1789         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790         PCOR(pcop)->rIdx = rIdx;
1791         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1792
1793         PCOR(pcop)->r->isFree = 0;
1794         PCOR(pcop)->r->wasUsed = 1;
1795
1796         pcop->type = PCOR(pcop)->r->pc_type;
1797
1798   return pcop;
1799 }
1800
1801 /*---------------------------------------------------------------------------------*/
1802 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1803 /*                 VR 030601                                                       */
1804 /*---------------------------------------------------------------------------------*/
1805 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1806 {
1807   pCodeOpReg2 *pcop2;
1808   pCodeOp *temp;
1809   
1810         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1811
1812         /* comment the following check, so errors to throw up */
1813 //      if(!pcop2)return NULL;
1814
1815         temp = pic16_popGet(aop_dst, offset);
1816         pcop2->pcop2 = temp;
1817         
1818   return PCOP(pcop2);
1819 }
1820
1821
1822
1823 /*--------------------------------------------------------------------------------.-*/
1824 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1825 /*                  VR 030601 , adapted by Hans Dorn                                */
1826 /*--------------------------------------------------------------------------------.-*/
1827 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1828 {
1829   pCodeOpReg2 *pcop2;
1830  
1831         pcop2 = (pCodeOpReg2 *)src;
1832         pcop2->pcop2 = dst;
1833         
1834         return PCOP(pcop2);
1835 }
1836
1837
1838
1839 /*---------------------------------------------------------------------------------*/
1840 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1841 /*                     movff instruction                                           */
1842 /*---------------------------------------------------------------------------------*/
1843 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1844 {
1845   pCodeOpReg2 *pcop2;
1846
1847         if(!noalloc) {
1848                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1849                 pcop2->pcop2 = pic16_popCopyReg(dst);
1850         } else {
1851                 /* the pCodeOp may be already allocated */
1852                 pcop2 = (pCodeOpReg2 *)(src);
1853                 pcop2->pcop2 = (pCodeOp *)(dst);
1854         }
1855
1856   return PCOP(pcop2);
1857 }
1858
1859
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popGet - asm operator to pcode operator conversion              */
1862 /*-----------------------------------------------------------------*/
1863 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1864 {
1865   //char *s = buffer ;
1866   char *rs;
1867   pCodeOp *pcop;
1868
1869     FENTRY2;
1870     /* offset is greater than
1871     size then zero */
1872
1873 //    if (offset > (aop->size - 1) &&
1874 //        aop->type != AOP_LIT)
1875 //      return NULL;  //zero;
1876
1877     /* depending on type */
1878     switch (aop->type) {
1879         
1880     case AOP_R0:
1881     case AOP_R1:
1882     case AOP_DPTR:
1883     case AOP_DPTR2:
1884         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1885         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1886         assert( 0 );
1887         return NULL;
1888
1889
1890     case AOP_FSR0:
1891     case AOP_FSR2:
1892       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1893       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1894       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1895       PCOR(pcop)->r->wasUsed = 1;
1896       PCOR(pcop)->r->isFree = 0;
1897       
1898       PCOR(pcop)->instance = offset;
1899       pcop->type = PCOR(pcop)->r->pc_type;
1900       return (pcop);
1901
1902     case AOP_IMMD:
1903       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1904       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1905
1906     case AOP_STA:
1907       /* pCodeOp is already allocated from aopForSym */
1908         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1909         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1910           
1911       return (pcop);
1912       
1913     case AOP_ACC:
1914       {
1915         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1916
1917         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1918
1919         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1920         
1921         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1922         PCOR(pcop)->rIdx = rIdx;
1923         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1924         PCOR(pcop)->r->wasUsed=1;
1925         PCOR(pcop)->r->isFree=0;
1926
1927         PCOR(pcop)->instance = offset;
1928         pcop->type = PCOR(pcop)->r->pc_type;
1929 //      rs = aop->aopu.aop_reg[offset]->name;
1930 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1931         return pcop;
1932
1933
1934 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1935 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1936
1937 //      assert( 0 );
1938       }
1939         
1940     case AOP_DIR:
1941       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1942       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1943         
1944     case AOP_REG:
1945       {
1946         int rIdx;
1947         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1948         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1949
1950         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1951         
1952         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1953 //      pcop->type = PO_GPR_REGISTER;
1954         PCOR(pcop)->rIdx = rIdx;
1955         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1956         PCOR(pcop)->r->wasUsed=1;
1957         PCOR(pcop)->r->isFree=0;
1958
1959         PCOR(pcop)->instance = offset;
1960         pcop->type = PCOR(pcop)->r->pc_type;
1961         
1962         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1963         rs = aop->aopu.aop_reg[offset]->name;
1964         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1965         return pcop;
1966       }
1967
1968     case AOP_CRY:
1969         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1970
1971       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1972       PCOR(pcop)->instance = offset;
1973       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1974       //if(PCOR(pcop)->r == NULL)
1975       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1976       return pcop;
1977         
1978     case AOP_LIT:
1979         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1980       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1981
1982     case AOP_STR:
1983       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1984       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1985
1986       /*
1987       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1989       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1990       pcop->type = PCOR(pcop)->r->pc_type;
1991       pcop->name = PCOR(pcop)->r->name;
1992
1993       return pcop;
1994       */
1995
1996     case AOP_PCODE:
1997       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1998                           __LINE__, 
1999                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2000       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2001 #if 1
2002         switch( aop->aopu.pcop->type ) {
2003                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
2004                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2005                 default:
2006                         assert( 0 );    /* should never reach here */;
2007         }
2008 #else
2009       PCOI(pcop)->offset = offset;
2010 #endif
2011       return pcop;
2012     }
2013
2014     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2015            "pic16_popGet got unsupported aop->type");
2016     exit(0);
2017 }
2018 /*-----------------------------------------------------------------*/
2019 /* pic16_aopPut - puts a string for a aop                                */
2020 /*-----------------------------------------------------------------*/
2021 void pic16_aopPut (asmop *aop, char *s, int offset)
2022 {
2023     char *d = buffer ;
2024     symbol *lbl ;
2025
2026     return;
2027
2028     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2029
2030     if (aop->size && offset > ( aop->size - 1)) {
2031         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2032                "pic16_aopPut got offset > aop->size");
2033         exit(0);
2034     }
2035
2036     /* will assign value to value */
2037     /* depending on where it is ofcourse */
2038     switch (aop->type) {
2039     case AOP_DIR:
2040       if (offset) {
2041         sprintf(d,"(%s + %d)",
2042                 aop->aopu.aop_dir,offset);
2043         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2044
2045       } else
2046             sprintf(d,"%s",aop->aopu.aop_dir);
2047         
2048         if (strcmp(d,s)) {
2049           DEBUGpic16_emitcode(";","%d",__LINE__);
2050           if(strcmp(s,"W"))
2051             pic16_emitcode("movf","%s,w",s);
2052           pic16_emitcode("movwf","%s",d);
2053
2054           if(strcmp(s,"W")) {
2055             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2056             if(offset >= aop->size) {
2057               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2058               break;
2059             } else
2060               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2061           }
2062
2063           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2064
2065
2066         }
2067         break;
2068         
2069     case AOP_REG:
2070       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2071         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2072           /*
2073             if (*s == '@'           ||
2074                 strcmp(s,"r0") == 0 ||
2075                 strcmp(s,"r1") == 0 ||
2076                 strcmp(s,"r2") == 0 ||
2077                 strcmp(s,"r3") == 0 ||
2078                 strcmp(s,"r4") == 0 ||
2079                 strcmp(s,"r5") == 0 ||
2080                 strcmp(s,"r6") == 0 || 
2081                 strcmp(s,"r7") == 0 )
2082                 pic16_emitcode("mov","%s,%s  ; %d",
2083                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2084             else
2085           */
2086
2087           if(strcmp(s,"W")==0 )
2088             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2089
2090           pic16_emitcode("movwf","%s",
2091                    aop->aopu.aop_reg[offset]->name);
2092
2093           if(strcmp(s,zero)==0) {
2094             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2095
2096           } else if(strcmp(s,"W")==0) {
2097             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2098             pcop->type = PO_GPR_REGISTER;
2099
2100             PCOR(pcop)->rIdx = -1;
2101             PCOR(pcop)->r = NULL;
2102
2103             DEBUGpic16_emitcode(";","%d",__LINE__);
2104             pcop->name = Safe_strdup(s);
2105             pic16_emitpcode(POC_MOVFW,pcop);
2106             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2107           } else if(strcmp(s,one)==0) {
2108             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2109             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2110           } else {
2111             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2112           }
2113         }
2114         break;
2115         
2116     case AOP_DPTR:
2117     case AOP_DPTR2:
2118     
2119     if (aop->type == AOP_DPTR2)
2120     {
2121         genSetDPTR(1);
2122     }
2123     
2124         if (aop->code) {
2125             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2126                    "pic16_aopPut writting to code space");
2127             exit(0);
2128         }
2129         
2130         while (offset > aop->coff) {
2131             aop->coff++;
2132             pic16_emitcode ("inc","dptr");
2133         }
2134         
2135         while (offset < aop->coff) {
2136             aop->coff-- ;
2137             pic16_emitcode("lcall","__decdptr");
2138         }
2139         
2140         aop->coff = offset;
2141         
2142         /* if not in accumulater */
2143         MOVA(s);        
2144         
2145         pic16_emitcode ("movx","@dptr,a");
2146         
2147     if (aop->type == AOP_DPTR2)
2148     {
2149         genSetDPTR(0);
2150     }
2151         break;
2152         
2153     case AOP_R0:
2154     case AOP_R1:
2155         while (offset > aop->coff) {
2156             aop->coff++;
2157             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2158         }
2159         while (offset < aop->coff) {
2160             aop->coff-- ;
2161             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2162         }
2163         aop->coff = offset;
2164         
2165         if (aop->paged) {
2166             MOVA(s);           
2167             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2168             
2169         } else
2170             if (*s == '@') {
2171                 MOVA(s);
2172                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2173             } else
2174                 if (strcmp(s,"r0") == 0 ||
2175                     strcmp(s,"r1") == 0 ||
2176                     strcmp(s,"r2") == 0 ||
2177                     strcmp(s,"r3") == 0 ||
2178                     strcmp(s,"r4") == 0 ||
2179                     strcmp(s,"r5") == 0 ||
2180                     strcmp(s,"r6") == 0 || 
2181                     strcmp(s,"r7") == 0 ) {
2182                     char buffer[10];
2183                     sprintf(buffer,"a%s",s);
2184                     pic16_emitcode("mov","@%s,%s",
2185                              aop->aopu.aop_ptr->name,buffer);
2186                 } else
2187                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2188         
2189         break;
2190         
2191     case AOP_STK:
2192         if (strcmp(s,"a") == 0)
2193             pic16_emitcode("push","acc");
2194         else
2195             pic16_emitcode("push","%s",s);
2196         
2197         break;
2198         
2199     case AOP_CRY:
2200         /* if bit variable */
2201         if (!aop->aopu.aop_dir) {
2202             pic16_emitcode("clr","a");
2203             pic16_emitcode("rlc","a");
2204         } else {
2205             if (s == zero) 
2206                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2207             else
2208                 if (s == one)
2209                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2210                 else
2211                     if (!strcmp(s,"c"))
2212                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2213                     else {
2214                         lbl = newiTempLabel(NULL);
2215                         
2216                         if (strcmp(s,"a")) {
2217                             MOVA(s);
2218                         }
2219                         pic16_emitcode("clr","c");
2220                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2221                         pic16_emitcode("cpl","c");
2222                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2223                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2224                     }
2225         }
2226         break;
2227         
2228     case AOP_STR:
2229         aop->coff = offset;
2230         if (strcmp(aop->aopu.aop_str[offset],s))
2231             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2232         break;
2233         
2234     case AOP_ACC:
2235         aop->coff = offset;
2236         if (!offset && (strcmp(s,"acc") == 0))
2237             break;
2238         
2239         if (strcmp(aop->aopu.aop_str[offset],s))
2240             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2241         break;
2242
2243     default :
2244         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2245 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2246 //             "pic16_aopPut got unsupported aop->type");
2247 //      exit(0);    
2248     }    
2249
2250 }
2251
2252 /*-----------------------------------------------------------------*/
2253 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2254 /*-----------------------------------------------------------------*/
2255 void pic16_mov2w (asmop *aop, int offset)
2256 {
2257   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2258
2259   if(is_LitAOp(aop))
2260     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2261   else
2262     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2263 }
2264
2265 static void mov2f(asmop *dst, asmop *src, int offset)
2266 {
2267   if(is_LitAOp(src)) {
2268     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2269     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2270   } else {
2271     if(pic16_sameRegsOfs(src, dst, offset))return;
2272     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2273                       pic16_popGet(dst, offset)));
2274   }
2275 }
2276
2277 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2278 {
2279   if(is_LitAOp(src)) {
2280     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2281     pic16_emitpcode(POC_MOVWF, dst);
2282   } else {
2283     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2284   }
2285 }
2286
2287 void pic16_testStackOverflow(void)
2288 {
2289 #define GSTACK_TEST_NAME        "__gstack_test"
2290
2291   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2292   
2293   {
2294     symbol *sym;
2295
2296       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2297       strcpy(sym->rname, GSTACK_TEST_NAME);
2298       checkAddSym(&externs, sym);
2299   }
2300
2301 }
2302
2303 /* push pcop into stack */
2304 void pic16_pushpCodeOp(pCodeOp *pcop)
2305 {
2306 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2307   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2308   if(pic16_options.gstack)
2309     pic16_testStackOverflow();
2310     
2311 }
2312
2313 /* pop pcop from stack */
2314 void pic16_poppCodeOp(pCodeOp *pcop)
2315 {
2316   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2317   if(pic16_options.gstack)
2318     pic16_testStackOverflow();
2319 }
2320
2321
2322 /*-----------------------------------------------------------------*/
2323 /* pushw - pushes wreg to stack                                    */
2324 /*-----------------------------------------------------------------*/
2325 void pushw(void)
2326 {
2327   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2328   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2329   if(pic16_options.gstack)
2330     pic16_testStackOverflow();
2331 }
2332
2333                 
2334 /*-----------------------------------------------------------------*/
2335 /* pushaop - pushes aop to stack                                   */
2336 /*-----------------------------------------------------------------*/
2337 void pushaop(asmop *aop, int offset)
2338 {
2339   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2340
2341   if(is_LitAOp(aop)) {
2342     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2343     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2344   } else {
2345     pic16_emitpcode(POC_MOVFF,
2346       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2347   }
2348
2349   if(pic16_options.gstack)
2350     pic16_testStackOverflow();
2351 }
2352
2353 /*-----------------------------------------------------------------*/
2354 /* popaop - pops aop from stack                                    */
2355 /*-----------------------------------------------------------------*/
2356 void popaop(asmop *aop, int offset)
2357 {
2358   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2359   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2360   if(pic16_options.gstack)
2361     pic16_testStackOverflow();
2362 }
2363
2364 void popaopidx(asmop *aop, int offset, int index)
2365 {
2366   int ofs=1;
2367
2368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2369
2370     if(STACK_MODEL_LARGE)ofs++;
2371
2372     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2373     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2374     if(pic16_options.gstack)
2375       pic16_testStackOverflow();
2376 }
2377
2378 #if !(USE_GENERIC_SIGNED_SHIFT)
2379 /*-----------------------------------------------------------------*/
2380 /* reAdjustPreg - points a register back to where it should        */
2381 /*-----------------------------------------------------------------*/
2382 static void reAdjustPreg (asmop *aop)
2383 {
2384     int size ;
2385
2386     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2387     aop->coff = 0;
2388     if ((size = aop->size) <= 1)
2389         return ;
2390     size-- ;
2391     switch (aop->type) {
2392         case AOP_R0 :
2393         case AOP_R1 :
2394             while (size--)
2395                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2396             break;          
2397         case AOP_DPTR :
2398         case AOP_DPTR2:
2399             if (aop->type == AOP_DPTR2)
2400             {
2401                 genSetDPTR(1);
2402             } 
2403             while (size--)
2404             {
2405                 pic16_emitcode("lcall","__decdptr");
2406             }
2407                 
2408             if (aop->type == AOP_DPTR2)
2409             {
2410                 genSetDPTR(0);
2411             }                
2412             break;  
2413
2414     }   
2415
2416 }
2417 #endif
2418
2419 #if 0
2420 /*-----------------------------------------------------------------*/
2421 /* opIsGptr: returns non-zero if the passed operand is             */   
2422 /* a generic pointer type.                                         */
2423 /*-----------------------------------------------------------------*/ 
2424 static int opIsGptr(operand *op)
2425 {
2426     sym_link *type = operandType(op);
2427     
2428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2429     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2430     {
2431         return 1;
2432     }
2433     return 0;        
2434 }
2435 #endif
2436
2437 /*-----------------------------------------------------------------*/
2438 /* pic16_getDataSize - get the operand data size                         */
2439 /*-----------------------------------------------------------------*/
2440 int pic16_getDataSize(operand *op)
2441 {
2442     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2443
2444
2445     return AOP_SIZE(op);
2446
2447     // tsd- in the pic port, the genptr size is 1, so this code here
2448     // fails. ( in the 8051 port, the size was 4).
2449 #if 0
2450     int size;
2451     size = AOP_SIZE(op);
2452     if (size == GPTRSIZE)
2453     {
2454         sym_link *type = operandType(op);
2455         if (IS_GENPTR(type))
2456         {
2457             /* generic pointer; arithmetic operations
2458              * should ignore the high byte (pointer type).
2459              */
2460             size--;
2461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2462         }
2463     }
2464     return size;
2465 #endif
2466 }
2467
2468 /*-----------------------------------------------------------------*/
2469 /* pic16_outAcc - output Acc                                             */
2470 /*-----------------------------------------------------------------*/
2471 void pic16_outAcc(operand *result)
2472 {
2473   int size,offset;
2474   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2475   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2476
2477
2478   size = pic16_getDataSize(result);
2479   if(size){
2480     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2481     size--;
2482     offset = 1;
2483     /* unsigned or positive */
2484     while(size--)
2485       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2486   }
2487
2488 }
2489
2490 /*-----------------------------------------------------------------*/
2491 /* pic16_outBitC - output a bit C                                  */
2492 /*                 Move to result the value of Carry flag -- VR    */
2493 /*-----------------------------------------------------------------*/
2494 void pic16_outBitC(operand *result)
2495 {
2496   int i;
2497
2498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2499
2500     /* if the result is bit */
2501     if (AOP_TYPE(result) == AOP_CRY) {
2502         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2503         pic16_aopPut(AOP(result),"c",0);
2504     } else {
2505
2506         i = AOP_SIZE(result);
2507         while(i--) {
2508                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2509         }
2510         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2511     }
2512 }
2513
2514 /*-----------------------------------------------------------------*/
2515 /* pic16_outBitOp - output a bit from Op                           */
2516 /*                 Move to result the value of set/clr op -- VR    */
2517 /*-----------------------------------------------------------------*/
2518 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2519 {
2520   int i;
2521
2522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2523
2524     /* if the result is bit */
2525     if (AOP_TYPE(result) == AOP_CRY) {
2526         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2527         pic16_aopPut(AOP(result),"c",0);
2528     } else {
2529
2530         i = AOP_SIZE(result);
2531         while(i--) {
2532                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2533         }
2534         pic16_emitpcode(POC_RRCF, pcop);          
2535         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2536     }
2537 }
2538
2539 /*-----------------------------------------------------------------*/
2540 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2541 /*-----------------------------------------------------------------*/
2542 void pic16_toBoolean(operand *oper)
2543 {
2544     int size = AOP_SIZE(oper) - 1;
2545     int offset = 1;
2546
2547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548
2549     if ( AOP_TYPE(oper) != AOP_ACC) {
2550       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2551     }
2552     while (size--) {
2553       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2554     }
2555 }
2556
2557
2558 #if !defined(GEN_Not)
2559 /*-----------------------------------------------------------------*/
2560 /* genNot - generate code for ! operation                          */
2561 /*-----------------------------------------------------------------*/
2562 static void pic16_genNot (iCode *ic)
2563 {
2564   symbol *tlbl;
2565   int size;
2566
2567   FENTRY;
2568   /* assign asmOps to operand & result */
2569   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2570   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2571
2572   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2573   /* if in bit space then a special case */
2574   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2575     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2576       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2577       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2578     } else {
2579       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2580       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2581       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2582     }
2583     goto release;
2584   }
2585
2586   size = AOP_SIZE(IC_LEFT(ic));
2587   if(size == 1) {
2588     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2589     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2590     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2591     goto release;
2592   }
2593   pic16_toBoolean(IC_LEFT(ic));
2594
2595   tlbl = newiTempLabel(NULL);
2596   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2597   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2598   pic16_outBitC(IC_RESULT(ic));
2599
2600  release:    
2601   /* release the aops */
2602   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2603   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2604 }
2605 #endif
2606
2607
2608 #if !defined(GEN_Cpl)
2609 /*-----------------------------------------------------------------*/
2610 /* genCpl - generate code for complement                           */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genCpl (iCode *ic)
2613 {
2614   int offset = 0;
2615   int size ;
2616
2617     FENTRY;
2618     /* assign asmOps to operand & result */
2619     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2621
2622     /* if both are in bit space then 
2623     a special case */
2624     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2625         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2626
2627         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2628         pic16_emitcode("cpl","c"); 
2629         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2630         goto release; 
2631     } 
2632
2633     size = AOP_SIZE(IC_RESULT(ic));
2634     while (size--) {
2635 /*
2636         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2637         MOVA(l);       
2638         pic16_emitcode("cpl","a");
2639         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2640 */
2641         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2642               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2643         } else {
2644                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2645                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2646         }
2647         offset++;
2648
2649     }
2650
2651
2652 release:
2653     /* release the aops */
2654     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2655     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2656 }
2657 #endif
2658
2659 /*-----------------------------------------------------------------*/
2660 /* genUminusFloat - unary minus for floating points                */
2661 /*-----------------------------------------------------------------*/
2662 static void genUminusFloat(operand *op,operand *result)
2663 {
2664   int size ,offset =0 ;
2665   
2666     FENTRY;
2667     /* for this we just need to flip the 
2668     first it then copy the rest in place */
2669     size = AOP_SIZE(op);
2670
2671     while(size--) {
2672       mov2f(AOP(result), AOP(op), offset);
2673       offset++;
2674     }
2675     
2676     /* toggle the MSB's highest bit */
2677     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2678 }
2679
2680 /*-----------------------------------------------------------------*/
2681 /* genUminus - unary minus code generation                         */
2682 /*-----------------------------------------------------------------*/
2683 static void genUminus (iCode *ic)
2684 {
2685   int size, i;
2686   sym_link *optype, *rtype;
2687
2688     FENTRY;     
2689     
2690     /* assign asmops */
2691     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2692     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2693
2694     /* if both in bit space then special case */
2695     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2696       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2697         
2698         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2699         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2700         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2701         goto release; 
2702     } 
2703
2704     optype = operandType(IC_LEFT(ic));
2705     rtype = operandType(IC_RESULT(ic));
2706
2707     /* if float then do float stuff */
2708     if (IS_FLOAT(optype)) {
2709       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2710       goto release;
2711     }
2712
2713     /* otherwise subtract from zero by taking the 2's complement */
2714     size = AOP_SIZE(IC_LEFT(ic));
2715
2716     for(i=0; i<size; i++) {
2717       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2718         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2719       else {
2720         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2721         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2722       }
2723     }
2724
2725     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2726     for(i=1; i<size; i++) {
2727       emitSKPNZ;
2728       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2729     }
2730
2731 release:
2732     /* release the aops */
2733     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2734     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2735 }
2736
2737 #if 0
2738 /*-----------------------------------------------------------------*/
2739 /* saveRegisters - will look for a call and save the registers     */
2740 /*-----------------------------------------------------------------*/
2741 static void saveRegisters(iCode *lic) 
2742 {
2743     int i;
2744     iCode *ic;
2745     bitVect *rsave;
2746     sym_link *dtype;
2747
2748     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2749     /* look for call */
2750     for (ic = lic ; ic ; ic = ic->next) 
2751         if (ic->op == CALL || ic->op == PCALL)
2752             break;
2753
2754     if (!ic) {
2755         fprintf(stderr,"found parameter push with no function call\n");
2756         return ;
2757     }
2758
2759     /* if the registers have been saved already then
2760     do nothing */
2761     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2762         return ;
2763
2764     /* find the registers in use at this time 
2765     and push them away to safety */
2766     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2767                           ic->rUsed);
2768
2769     ic->regsSaved = 1;
2770     if (options.useXstack) {
2771         if (bitVectBitValue(rsave,R0_IDX))
2772             pic16_emitcode("mov","b,r0");
2773         pic16_emitcode("mov","r0,%s",spname);
2774         for (i = 0 ; i < pic16_nRegs ; i++) {
2775             if (bitVectBitValue(rsave,i)) {
2776                 if (i == R0_IDX)
2777                     pic16_emitcode("mov","a,b");
2778                 else
2779                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2780                 pic16_emitcode("movx","@r0,a");
2781                 pic16_emitcode("inc","r0");
2782             }
2783         }
2784         pic16_emitcode("mov","%s,r0",spname);
2785         if (bitVectBitValue(rsave,R0_IDX))
2786             pic16_emitcode("mov","r0,b");           
2787     }// else
2788     //for (i = 0 ; i < pic16_nRegs ; i++) {
2789     //    if (bitVectBitValue(rsave,i))
2790     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2791     //}
2792
2793     dtype = operandType(IC_LEFT(ic));
2794     if (currFunc && dtype && 
2795         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2796         IFFUNC_ISISR(currFunc->type) &&
2797         !ic->bankSaved) 
2798
2799         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2800
2801 }
2802 /*-----------------------------------------------------------------*/
2803 /* unsaveRegisters - pop the pushed registers                      */
2804 /*-----------------------------------------------------------------*/
2805 static void unsaveRegisters (iCode *ic)
2806 {
2807     int i;
2808     bitVect *rsave;
2809
2810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2811     /* find the registers in use at this time 
2812     and push them away to safety */
2813     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2814                           ic->rUsed);
2815     
2816     if (options.useXstack) {
2817         pic16_emitcode("mov","r0,%s",spname);   
2818         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2819             if (bitVectBitValue(rsave,i)) {
2820                 pic16_emitcode("dec","r0");
2821                 pic16_emitcode("movx","a,@r0");
2822                 if (i == R0_IDX)
2823                     pic16_emitcode("mov","b,a");
2824                 else
2825                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2826             }       
2827
2828         }
2829         pic16_emitcode("mov","%s,r0",spname);
2830         if (bitVectBitValue(rsave,R0_IDX))
2831             pic16_emitcode("mov","r0,b");
2832     } //else
2833     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2834     //    if (bitVectBitValue(rsave,i))
2835     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2836     //}
2837
2838 }  
2839 #endif
2840
2841 #if 0  // patch 14
2842 /*-----------------------------------------------------------------*/
2843 /* pushSide -                                                      */
2844 /*-----------------------------------------------------------------*/
2845 static void pushSide(operand * oper, int size)
2846 {
2847         int offset = 0;
2848     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2849         while (size--) {
2850                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2851                 if (AOP_TYPE(oper) != AOP_REG &&
2852                     AOP_TYPE(oper) != AOP_DIR &&
2853                     strcmp(l,"a") ) {
2854                         pic16_emitcode("mov","a,%s",l);
2855                         pic16_emitcode("push","acc");
2856                 } else
2857                         pic16_emitcode("push","%s",l);
2858         }
2859 }
2860 #endif // patch 14
2861
2862 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2863 {
2864   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2865     pic16_emitpcode(POC_MOVFW, src);
2866     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2867   } else {
2868     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2869         src, pic16_popGet(AOP(op), offset)));
2870   }
2871 }
2872
2873
2874 /*-----------------------------------------------------------------*/
2875 /* assignResultValue - assign results to oper, rescall==1 is       */
2876 /*                     called from genCall() or genPcall()         */
2877 /*-----------------------------------------------------------------*/
2878 static void assignResultValue(operand * oper, int rescall)
2879 {
2880   int size = AOP_SIZE(oper);
2881   int offset=0;
2882   
2883     FENTRY2;
2884 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2885     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2886
2887     if(rescall) {
2888       /* assign result from a call/pcall function() */
2889                 
2890       /* function results are stored in a special order,
2891        * see top of file with Function return policy, or manual */
2892
2893       if(size <= 4) {
2894         /* 8-bits, result in WREG */
2895         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2896                         
2897         if(size>1) {
2898           /* 16-bits, result in PRODL:WREG */
2899           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2900         }
2901                         
2902         if(size>2) {
2903           /* 24-bits, result in PRODH:PRODL:WREG */
2904           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2905         }
2906                         
2907         if(size>3) {
2908           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2909           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2910         }
2911       
2912       } else {
2913         /* >32-bits, result on stack, and FSR0 points to beginning.
2914          * Fix stack when done */
2915         /* FIXME FIXME */
2916 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2917         while (size--) {
2918 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2919 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2920                 
2921           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2922           GpsuedoStkPtr++;
2923         }
2924                         
2925         /* fix stack */
2926         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2927         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2928         if(STACK_MODEL_LARGE) {
2929           emitSKPNC;
2930           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2931         }
2932       }                 
2933     } else {
2934       int areg = 0;             /* matching argument register */
2935       
2936 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2937       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2938
2939
2940       /* its called from genReceive (probably) -- VR */
2941       /* I hope this code will not be called from somewhere else in the future! 
2942        * We manually set the pseudo stack pointer in genReceive. - dw
2943        */
2944       if(!GpsuedoStkPtr && _G.useWreg) {
2945 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2946
2947         /* The last byte in the assignment is in W */
2948         if(areg <= GpsuedoStkPtr) {
2949           size--;
2950           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2951           offset++;
2952 //          debugf("receive from WREG\n", 0);
2953         }
2954         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2955       }
2956 //      GpsuedoStkPtr++;
2957       _G.stack_lat = AOP_SIZE(oper)-1;
2958
2959       while (size) {
2960         size--;
2961         GpsuedoStkPtr++;
2962         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2963 //        debugf("receive from STACK\n", 0);
2964         offset++;
2965       }
2966     }
2967 }
2968
2969
2970 /*-----------------------------------------------------------------*/
2971 /* genIpush - generate code for pushing this gets a little complex */
2972 /*-----------------------------------------------------------------*/
2973 static void genIpush (iCode *ic)
2974 {
2975 //  int size, offset=0;
2976
2977   FENTRY;
2978   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2979
2980   if(ic->parmPush) {
2981     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2982
2983     /* send to stack as normal */
2984     addSet(&_G.sendSet,ic);
2985 //    addSetHead(&_G.sendSet,ic);
2986     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2987   }
2988
2989         
2990 #if 0
2991     int size, offset = 0 ;
2992     char *l;
2993
2994
2995     /* if this is not a parm push : ie. it is spill push 
2996     and spill push is always done on the local stack */
2997     if (!ic->parmPush) {
2998
2999         /* and the item is spilt then do nothing */
3000         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3001             return ;
3002
3003         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3004         size = AOP_SIZE(IC_LEFT(ic));
3005         /* push it on the stack */
3006         while(size--) {
3007             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3008             if (*l == '#') {
3009                 MOVA(l);
3010                 l = "acc";
3011             }
3012             pic16_emitcode("push","%s",l);
3013         }
3014         return ;        
3015     }
3016
3017     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3018 #endif
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genIpop - recover the registers: can happen only for spilling   */
3023 /*-----------------------------------------------------------------*/
3024 static void genIpop (iCode *ic)
3025 {
3026   FENTRY;
3027   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3028 #if 0
3029     int size,offset ;
3030
3031
3032     /* if the temp was not pushed then */
3033     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3034         return ;
3035
3036     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3037     size = AOP_SIZE(IC_LEFT(ic));
3038     offset = (size-1);
3039     while (size--) 
3040         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3041                                    FALSE,TRUE));
3042
3043     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3044 #endif
3045 }
3046
3047 #if 0
3048 /*-----------------------------------------------------------------*/
3049 /* unsaverbank - restores the resgister bank from stack            */
3050 /*-----------------------------------------------------------------*/
3051 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3052 {
3053   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3054 #if 0
3055     int i;
3056     asmop *aop ;
3057     regs *r = NULL;
3058
3059     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3060     if (popPsw) {
3061         if (options.useXstack) {
3062             aop = newAsmop(0);
3063             r = getFreePtr(ic,&aop,FALSE);
3064             
3065             
3066             pic16_emitcode("mov","%s,_spx",r->name);
3067             pic16_emitcode("movx","a,@%s",r->name);
3068             pic16_emitcode("mov","psw,a");
3069             pic16_emitcode("dec","%s",r->name);
3070             
3071         }else
3072             pic16_emitcode ("pop","psw");
3073     }
3074
3075     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3076         if (options.useXstack) {       
3077             pic16_emitcode("movx","a,@%s",r->name);
3078             //pic16_emitcode("mov","(%s+%d),a",
3079             //       regspic16[i].base,8*bank+regspic16[i].offset);
3080             pic16_emitcode("dec","%s",r->name);
3081
3082         } else 
3083           pic16_emitcode("pop",""); //"(%s+%d)",
3084         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3085     }
3086
3087     if (options.useXstack) {
3088
3089         pic16_emitcode("mov","_spx,%s",r->name);
3090         pic16_freeAsmop(NULL,aop,ic,TRUE);
3091
3092     }
3093 #endif 
3094 }
3095
3096 /*-----------------------------------------------------------------*/
3097 /* saverbank - saves an entire register bank on the stack          */
3098 /*-----------------------------------------------------------------*/
3099 static void saverbank (int bank, iCode *ic, bool pushPsw)
3100 {
3101   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3102 #if 0
3103     int i;
3104     asmop *aop ;
3105     regs *r = NULL;
3106
3107     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3108     if (options.useXstack) {
3109
3110         aop = newAsmop(0);
3111         r = getFreePtr(ic,&aop,FALSE);  
3112         pic16_emitcode("mov","%s,_spx",r->name);
3113
3114     }
3115
3116     for (i = 0 ; i < pic16_nRegs ;i++) {
3117         if (options.useXstack) {
3118             pic16_emitcode("inc","%s",r->name);
3119             //pic16_emitcode("mov","a,(%s+%d)",
3120             //         regspic16[i].base,8*bank+regspic16[i].offset);
3121             pic16_emitcode("movx","@%s,a",r->name);           
3122         } else 
3123           pic16_emitcode("push","");// "(%s+%d)",
3124                      //regspic16[i].base,8*bank+regspic16[i].offset);
3125     }
3126     
3127     if (pushPsw) {
3128         if (options.useXstack) {
3129             pic16_emitcode("mov","a,psw");
3130             pic16_emitcode("movx","@%s,a",r->name);     
3131             pic16_emitcode("inc","%s",r->name);
3132             pic16_emitcode("mov","_spx,%s",r->name);       
3133             pic16_freeAsmop (NULL,aop,ic,TRUE);
3134             
3135         } else
3136             pic16_emitcode("push","psw");
3137         
3138         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3139     }
3140     ic->bankSaved = 1;
3141 #endif
3142 }
3143 #endif  /* 0 */
3144
3145
3146 static int wparamCmp(void *p1, void *p2)
3147 {
3148   return (!strcmp((char *)p1, (char *)p2));
3149 }
3150
3151 int inWparamList(char *s)
3152 {
3153   return isinSetWith(wparamList, s, wparamCmp);
3154
3155
3156
3157 /*-----------------------------------------------------------------*/
3158 /* genCall - generates a call statement                            */
3159 /*-----------------------------------------------------------------*/
3160 static void genCall (iCode *ic)
3161 {
3162   sym_link *ftype;   
3163   int stackParms=0;
3164   int use_wreg=0;
3165   int inwparam=0;
3166   char *fname;
3167   
3168     FENTRY;
3169
3170     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3171     /* if caller saves & we have not saved then */
3172 //    if (!ic->regsSaved)
3173 //      saveRegisters(ic);
3174
3175         /* initialise stackParms for IPUSH pushes */
3176 //      stackParms = psuedoStkPtr;
3177 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3178     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3179     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3180
3181 #if 0
3182     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3183 #endif
3184
3185     /* if send set is not empty the assign */
3186     if (_G.sendSet) {
3187       iCode *sic;
3188       int psuedoStkPtr=-1; 
3189       int firstTimeThruLoop = 1;
3190
3191
3192         /* reverse sendSet if function is not reentrant */
3193         if(!IFFUNC_ISREENT(ftype))
3194           _G.sendSet = reverseSet(_G.sendSet);
3195
3196         /* First figure how many parameters are getting passed */
3197         stackParms = 0;
3198         use_wreg = 0;
3199         
3200         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3201           int size;
3202 //          int offset = 0;
3203
3204             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3205             size = AOP_SIZE(IC_LEFT(sic));
3206
3207             stackParms += size;
3208
3209             /* pass the last byte through WREG */
3210             if(inwparam) {
3211
3212               while (size--) {
3213                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3214                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3215                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3216
3217                 if(!firstTimeThruLoop) {
3218                   /* If this is not the first time we've been through the loop
3219                    * then we need to save the parameter in a temporary
3220                    * register. The last byte of the last parameter is
3221                    * passed in W. */
3222
3223                   pushw();
3224 //                  --psuedoStkPtr;             // sanity check
3225                   use_wreg = 1;
3226                 }
3227                 
3228                 firstTimeThruLoop=0;
3229
3230                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3231
3232 //                offset++;
3233               }
3234             } else {
3235               /* all arguments are passed via stack */
3236               use_wreg = 0;
3237
3238               while (size--) {
3239                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3240                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3241                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3242
3243 //                pushaop(AOP(IC_LEFT(sic)), size);
3244                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3245                 pushw();
3246               }
3247             }
3248
3249             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3250           }
3251
3252           if(inwparam) {
3253             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3254               pushw();  /* save last parameter to stack if functions has varargs */
3255               use_wreg = 0;
3256             } else
3257               use_wreg = 1;
3258           } else use_wreg = 0;
3259
3260           _G.stackRegSet = _G.sendSet;
3261           _G.sendSet = NULL;
3262     }
3263
3264     /* make the call */
3265     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3266
3267     GpsuedoStkPtr=0;
3268     
3269     /* if we need to assign a result value */
3270     if ((IS_ITEMP(IC_RESULT(ic))
3271           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3272               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3273         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3274
3275       _G.accInUse++;
3276       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3277       _G.accInUse--;
3278
3279       assignResultValue(IC_RESULT(ic), 1);
3280
3281       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3283                 
3284       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3285     }
3286
3287     if(!stackParms && ic->parmBytes) {
3288       stackParms = ic->parmBytes;
3289     }
3290       
3291     stackParms -= use_wreg;
3292     
3293     if(stackParms>0) {
3294       if(stackParms == 1) {
3295         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3296       } else {
3297         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3298         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3299       }
3300       if(STACK_MODEL_LARGE) {
3301         emitSKPNC;
3302         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3303       }
3304     }
3305
3306 #if 0
3307     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3308 #endif
3309
3310     /* adjust the stack for parameters if required */
3311 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3312
3313 #if 0
3314       /* if register bank was saved then pop them */
3315       if (ic->bankSaved)
3316         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3317
3318       /* if we hade saved some registers then unsave them */
3319       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3320         unsaveRegisters (ic);
3321 #endif
3322 }
3323
3324
3325
3326 /*-----------------------------------------------------------------*/
3327 /* genPcall - generates a call by pointer statement                */
3328 /*            new version, created from genCall - HJD              */
3329 /*-----------------------------------------------------------------*/
3330 static void genPcall (iCode *ic)
3331 {
3332   sym_link *ftype, *fntype;
3333   int stackParms=0;
3334   symbol *retlbl = newiTempLabel(NULL);
3335   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3336   
3337     FENTRY;
3338
3339     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3340     fntype = operandType( IC_LEFT(ic) )->next;
3341
3342     /* if send set is not empty the assign */
3343     if (_G.sendSet) {
3344       iCode *sic;
3345       int psuedoStkPtr=-1; 
3346
3347       /* reverse sendSet if function is not reentrant */
3348       if(!IFFUNC_ISREENT(fntype))
3349         _G.sendSet = reverseSet(_G.sendSet);
3350
3351       stackParms = 0;
3352       
3353       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3354         int size;
3355
3356           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3357           size = AOP_SIZE(IC_LEFT(sic));
3358           stackParms += size;
3359
3360           /* all parameters are passed via stack, since WREG is clobbered
3361            * by the calling sequence */
3362           while (size--) {
3363             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3366
3367             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3368             pushw();
3369           }
3370
3371           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3372       }
3373
3374       _G.stackRegSet = _G.sendSet;
3375       _G.sendSet = NULL;
3376     }
3377
3378     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3379
3380     // push return address
3381     // push $ on return stack, then replace with retlbl
3382
3383     pic16_emitpcodeNULLop(POC_PUSH);
3384
3385     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3386     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3387     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3388     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3389     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3390     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3391
3392     /* make the call by writing the pointer into pc */
3393     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3394     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3395
3396     // note: MOVFF to PCL not allowed
3397     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3398     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3399
3400
3401     /* return address is here: (X) */
3402     pic16_emitpLabelFORCE(retlbl->key);
3403
3404     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3405
3406     GpsuedoStkPtr=0;
3407     /* if we need assign a result value */
3408     if ((IS_ITEMP(IC_RESULT(ic))
3409           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3410               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3411         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3412
3413       _G.accInUse++;
3414       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3415       _G.accInUse--;
3416
3417       assignResultValue(IC_RESULT(ic), 1);
3418
3419       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3421                 
3422       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3423     }
3424
3425 //    stackParms -= use_wreg;
3426     
3427     if(stackParms>0) {
3428       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3429       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3430       if(STACK_MODEL_LARGE) {
3431         emitSKPNC;
3432         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3433       }
3434     }
3435 }
3436
3437 /*-----------------------------------------------------------------*/
3438 /* resultRemat - result  is rematerializable                       */
3439 /*-----------------------------------------------------------------*/
3440 static int resultRemat (iCode *ic)
3441 {
3442   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3443   if (SKIP_IC(ic) || ic->op == IFX)
3444     return 0;
3445
3446   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3447     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3448     if (sym->remat && !POINTER_SET(ic)) 
3449       return 1;
3450   }
3451
3452   return 0;
3453 }
3454
3455 #if defined(__BORLANDC__) || defined(_MSC_VER)
3456 #define STRCASECMP stricmp
3457 #else
3458 #define STRCASECMP strcasecmp
3459 #endif
3460
3461 #if 0
3462 /*-----------------------------------------------------------------*/
3463 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3464 /*-----------------------------------------------------------------*/
3465 static bool inExcludeList(char *s)
3466 {
3467   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3468     int i =0;
3469     
3470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3471     if (options.excludeRegs[i] &&
3472     STRCASECMP(options.excludeRegs[i],"none") == 0)
3473         return FALSE ;
3474
3475     for ( i = 0 ; options.excludeRegs[i]; i++) {
3476         if (options.excludeRegs[i] &&
3477         STRCASECMP(s,options.excludeRegs[i]) == 0)
3478             return TRUE;
3479     }
3480     return FALSE ;
3481 }
3482 #endif
3483
3484 /*-----------------------------------------------------------------*/
3485 /* genFunction - generated code for function entry                 */
3486 /*-----------------------------------------------------------------*/
3487 static void genFunction (iCode *ic)
3488 {
3489   symbol *sym;
3490   sym_link *ftype;
3491   
3492     FENTRY;
3493     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3494
3495     pic16_labelOffset += (max_key+4);
3496     max_key=0;
3497     GpsuedoStkPtr=0;
3498     _G.nRegsSaved = 0;
3499         
3500     ftype = operandType(IC_LEFT(ic));
3501     sym = OP_SYMBOL(IC_LEFT(ic));
3502
3503     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3504       /* create an absolute section at the interrupt vector:
3505        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3506       symbol *asym;
3507       char asymname[128];
3508       pBlock *apb;
3509
3510         {
3511           int i, found=-1;
3512
3513             sym = OP_SYMBOL( IC_LEFT(ic));
3514             for(i=0;i<=2;i++) {
3515               if(interrupts[i]->name
3516                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3517                   found = i;
3518                   break;
3519               }
3520             }
3521                         
3522             if(found == -1) {
3523               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3524                             __FILE__, __LINE__, sym->name);
3525               assert( 0 );
3526             }
3527             _G.interruptvector = found;
3528         }
3529
3530         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3531         asym = newSymbol(asymname, 0);
3532
3533         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3534         pic16_addpBlock( apb );
3535
3536         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3537         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3538         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3539                 
3540         /* mark the end of this tiny function */
3541         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3542
3543         {
3544           absSym *abSym;
3545
3546             abSym = Safe_calloc(1, sizeof(absSym));
3547             strcpy(abSym->name, asymname);
3548
3549             switch( _G.interruptvector ) {
3550               case 0: abSym->address = 0x000000; break;
3551               case 1: abSym->address = 0x000008; break;
3552               case 2: abSym->address = 0x000018; break;
3553             }
3554
3555             /* relocate interrupt vectors if needed */
3556             abSym->address += pic16_options.ivt_loc;
3557
3558             addSet(&absSymSet, abSym);
3559         }
3560     }
3561
3562     /* create the function header */
3563     pic16_emitcode(";","-----------------------------------------");
3564     pic16_emitcode(";"," function %s",sym->name);
3565     pic16_emitcode(";","-----------------------------------------");
3566
3567     pic16_emitcode("","%s:",sym->rname);
3568     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3569
3570
3571     {
3572       absSym *ab;
3573
3574         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3575           if(!strcmp(ab->name, sym->rname)) {
3576             pic16_pBlockConvert2Absolute(pb);
3577             break;
3578           }
3579         }
3580     }
3581
3582
3583     if(IFFUNC_ISNAKED(ftype)) {
3584       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3585       return;
3586     }
3587         
3588     /* if critical function then turn interrupts off */
3589     if (IFFUNC_ISCRITICAL(ftype)) {
3590       //pic16_emitcode("clr","ea");
3591     }
3592
3593     _G.fregsUsed = sym->regsUsed;
3594
3595     /* if this is an interrupt service routine then
3596      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3597     if (IFFUNC_ISISR(sym->type)) {
3598         _G.usefastretfie = 1;   /* use shadow registers by default */
3599         
3600         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3601         if(!(_G.interruptvector == 1)) {
3602           /* do not save WREG,STATUS,BSR for high priority interrupts
3603            * because they are stored in the hardware shadow registers already */
3604           _G.usefastretfie = 0;
3605           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3606           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3607           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3608         }
3609
3610         /* these should really be optimized somehow, because not all
3611          * interrupt handlers modify them */
3612         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3613         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3614         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3615         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3616         
3617 //        pic16_pBlockConvert2ISR(pb);
3618                 
3619     }
3620
3621     /* emit code to setup stack frame if user enabled,
3622      * and function is not main() */
3623          
3624     //fprintf(stderr, "function name: %s\n", sym->name);
3625     if(strcmp(sym->name, "main")) {
3626       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3627         /* setup the stack frame */
3628         if(STACK_MODEL_LARGE)
3629           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3630         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3631
3632         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3633         if(STACK_MODEL_LARGE)
3634           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3635       }
3636     }
3637
3638     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3639           && sym->stack) {
3640
3641       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3642
3643       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3644       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3645       emitSKPC;
3646       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3647     }
3648           
3649     if(inWparamList(sym->name)) {
3650       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3651         _G.useWreg = 0;
3652       else
3653         _G.useWreg = 1;
3654     } else
3655       _G.useWreg = 0;
3656
3657     /* if callee-save to be used for this function
3658      * then save the registers being used in this function */
3659 //    if (IFFUNC_CALLEESAVES(sym->type))
3660     {
3661       int i;
3662
3663         /* if any registers used */
3664         if (sym->regsUsed) {
3665           /* save the registers used */
3666           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3667           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3668           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3669             if (bitVectBitValue(sym->regsUsed,i)) {
3670               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3671               _G.nRegsSaved++;
3672
3673               if(!pic16_regWithIdx(i)->wasUsed) {
3674                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3675                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3676                 pic16_regWithIdx(i)->wasUsed = 1;
3677               }
3678             }
3679           }
3680           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3681         }
3682     }
3683         
3684     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3685 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3686 }
3687
3688 /*-----------------------------------------------------------------*/
3689 /* genEndFunction - generates epilogue for functions               */
3690 /*-----------------------------------------------------------------*/
3691 static void genEndFunction (iCode *ic)
3692 {
3693   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3694
3695     FENTRY;
3696
3697     if(IFFUNC_ISNAKED(sym->type)) {
3698       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3699       return;
3700     }
3701
3702     _G.stack_lat = 0;
3703
3704     /* add code for ISCRITICAL */
3705     if(IFFUNC_ISCRITICAL(sym->type)) {
3706       /* if critical function, turn on interrupts */
3707       
3708       /* TODO: add code here -- VR */
3709     }
3710     
3711 //    sym->regsUsed = _G.fregsUsed;
3712     
3713     /* now we need to restore the registers */
3714     /* if any registers used */
3715     if (sym->regsUsed) {
3716       int i;
3717
3718         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3719         /* restore registers used */
3720         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3721         for ( i = sym->regsUsed->size; i >= 0; i--) {
3722           if (bitVectBitValue(sym->regsUsed,i)) {
3723             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3724             _G.nRegsSaved--;
3725           }
3726         }
3727         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3728
3729     }
3730
3731     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3732           && sym->stack) {
3733       if (sym->stack == 1) {
3734         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3735         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3736       } else {
3737         // we have to add more than one...
3738         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3739         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3740         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3741         emitSKPNC;
3742         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3743         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3744         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3745       }
3746     }
3747
3748     if(strcmp(sym->name, "main")) {
3749       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3750         /* restore stack frame */
3751         if(STACK_MODEL_LARGE)
3752           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3753         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3754       }
3755     }
3756
3757     _G.useWreg = 0;
3758
3759     if (IFFUNC_ISISR(sym->type)) {
3760       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3762       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3763       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3764
3765       if(!(_G.interruptvector == 1)) {
3766         /* do not restore interrupt vector for WREG,STATUS,BSR
3767          * for high priority interrupt, see genFunction */
3768         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3769         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3770         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3771       }
3772       _G.interruptvector = 0;           /* sanity check */
3773
3774
3775       /* if debug then send end of function */
3776 /*      if (options.debug && currFunc)  */
3777       if (currFunc) {
3778         debugFile->writeEndFunction (currFunc, ic, 1);
3779       }
3780         
3781       if(_G.usefastretfie)
3782         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3783       else
3784         pic16_emitpcodeNULLop(POC_RETFIE);
3785
3786       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3787       
3788       _G.usefastretfie = 0;
3789       return;
3790     }
3791
3792     if (IFFUNC_ISCRITICAL(sym->type)) {
3793       pic16_emitcode("setb","ea");
3794     }
3795
3796     /* if debug then send end of function */
3797     if (currFunc) {
3798       debugFile->writeEndFunction (currFunc, ic, 1);
3799     }
3800
3801     /* insert code to restore stack frame, if user enabled it
3802      * and function is not main() */
3803          
3804
3805     pic16_emitpcodeNULLop(POC_RETURN);
3806
3807     /* Mark the end of a function */
3808     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3809 }
3810
3811
3812 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3813 {
3814   if(is_LitOp(op)) {
3815     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3816       if(lit == 0) {
3817         pic16_emitpcode(POC_CLRF, dest);
3818       } else {
3819         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3820         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3821       }
3822   } else {
3823     if(dest->type == PO_WREG && (offset == 0)) {
3824       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3825       return;
3826     }
3827     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3828   }
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* genRet - generate code for return statement                     */
3833 /*-----------------------------------------------------------------*/
3834 static void genRet (iCode *ic)
3835 {
3836   int size;
3837   operand *left;
3838
3839     FENTRY;
3840         /* if we have no return value then
3841          * just generate the "ret" */
3842         
3843         if (!IC_LEFT(ic)) 
3844                 goto jumpret;       
3845     
3846         /* we have something to return then
3847          * move the return value into place */
3848         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3849         size = AOP_SIZE(IC_LEFT(ic));
3850
3851         if(size <= 4) {
3852                 if(size>3) {
3853                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3854 //                      pic16_emitpcode(POC_MOVFF,
3855 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3856                 }
3857                 if(size>2) {
3858                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3859 //                      pic16_emitpcode(POC_MOVFF,
3860 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3861                 }
3862                 if(size>1) {
3863                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3864 //                      pic16_emitpcode(POC_MOVFF,
3865 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3866                 }
3867
3868 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3869
3870                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3871 //              pic16_emitpcode(POC_MOVFF,
3872 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3873
3874         } else {
3875                 /* >32-bits, setup stack and FSR0 */
3876                 while (size--) {
3877 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3878 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3879
3880                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3881
3882 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3883                         GpsuedoStkPtr++;
3884                 }
3885                         
3886                 /* setup FSR0 */
3887                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3888                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3889
3890                 if(STACK_MODEL_LARGE) {
3891                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3892                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3893                 } else {
3894                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3895                 }
3896         }
3897                                 
3898 #if 0
3899         /* old code, left here for reference -- VR */    
3900         while (size--) {
3901           char *l ;
3902
3903                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3904                         /* #NOCHANGE */
3905                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3906                         pic16_emitpcomment("push %s",l);
3907                         pushed++;
3908                 } else {
3909                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3910                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3911                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3912                         
3913                         if (strcmp(fReturn[offset],l)) {
3914                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3915                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3916                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3917                                 } else {
3918                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3919                                 }
3920                                 
3921                                 if(size) {
3922                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3923                                 }
3924                                 offset++;
3925                         }
3926                 }
3927         }    
3928
3929         if (pushed) {
3930                 while(pushed) {
3931                         pushed--;
3932                         if (strcmp(fReturn[pushed],"a"))
3933                                 pic16_emitcode("pop",fReturn[pushed]);
3934                         else
3935                                 pic16_emitcode("pop","acc");
3936                 }
3937         }
3938 #endif
3939
3940
3941         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3942     
3943 jumpret:
3944         /* generate a jump to the return label
3945          * if the next is not the return statement */
3946         if (!(ic->next && ic->next->op == LABEL
3947                 && IC_LABEL(ic->next) == returnLabel)) {
3948         
3949                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3950                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3951         }
3952 }
3953
3954 /*-----------------------------------------------------------------*/
3955 /* genLabel - generates a label                                    */
3956 /*-----------------------------------------------------------------*/
3957 static void genLabel (iCode *ic)
3958 {
3959   FENTRY;
3960
3961   /* special case never generate */
3962   if (IC_LABEL(ic) == entryLabel)
3963     return ;
3964
3965   pic16_emitpLabel(IC_LABEL(ic)->key);
3966 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3967 }
3968
3969 /*-----------------------------------------------------------------*/
3970 /* genGoto - generates a goto                                      */
3971 /*-----------------------------------------------------------------*/
3972 //tsd
3973 static void genGoto (iCode *ic)
3974 {
3975   FENTRY;
3976   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3977 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3978 }
3979
3980
3981 /*-----------------------------------------------------------------*/
3982 /* genMultbits :- multiplication of bits                           */
3983 /*-----------------------------------------------------------------*/
3984 static void genMultbits (operand *left, 
3985                          operand *right, 
3986                          operand *result)
3987 {
3988   FENTRY;
3989
3990   if(!pic16_sameRegs(AOP(result),AOP(right)))
3991     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3992
3993   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3994   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3995   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3996
3997 }
3998
3999
4000 /*-----------------------------------------------------------------*/
4001 /* genMultOneByte : 8 bit multiplication & division                */
4002 /*-----------------------------------------------------------------*/
4003 static void genMultOneByte (operand *left,
4004                             operand *right,
4005                             operand *result)
4006 {
4007
4008   FENTRY;
4009   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4010   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4011
4012   /* (if two literals, the value is computed before) */
4013   /* if one literal, literal on the right */
4014   if (AOP_TYPE(left) == AOP_LIT){
4015     operand *t = right;
4016     right = left;
4017     left = t;
4018   }
4019
4020         /* size is already checked in genMult == 1 */
4021 //      size = AOP_SIZE(result);
4022
4023         if (AOP_TYPE(right) == AOP_LIT){
4024                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4025                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4026                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4027                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4028         } else {
4029                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4030                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4031                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4032                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4033         }
4034         
4035         pic16_genMult8X8_8 (left, right,result);
4036 }
4037
4038 /*-----------------------------------------------------------------*/
4039 /* genMultOneWord : 16 bit multiplication                          */
4040 /*-----------------------------------------------------------------*/
4041 static void genMultOneWord (operand *left,
4042                             operand *right,
4043                             operand *result)
4044 {
4045   FENTRY;
4046   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4047   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4048
4049   /* (if two literals, the value is computed before)
4050    * if one literal, literal on the right */
4051   if (AOP_TYPE(left) == AOP_LIT){
4052     operand *t = right;
4053     right = left;
4054     left = t;
4055   }
4056
4057   /* size is checked already == 2 */
4058 //  size = AOP_SIZE(result);
4059
4060   if (AOP_TYPE(right) == AOP_LIT) {
4061     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4062       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4063       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4064       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4065   } else {
4066     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4067       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4068       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4069       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4070   }
4071         
4072   pic16_genMult16X16_16(left, right,result);
4073 }
4074
4075 /*-----------------------------------------------------------------*/
4076 /* genMultOneLong : 32 bit multiplication                          */
4077 /*-----------------------------------------------------------------*/
4078 static void genMultOneLong (operand *left,
4079                             operand *right,
4080                             operand *result)
4081 {
4082   FENTRY;
4083   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4084   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4085
4086   /* (if two literals, the value is computed before)
4087    * if one literal, literal on the right */
4088   if (AOP_TYPE(left) == AOP_LIT){
4089     operand *t = right;
4090     right = left;
4091     left = t;
4092   }
4093
4094   /* size is checked already == 4 */
4095 //  size = AOP_SIZE(result);
4096
4097   if (AOP_TYPE(right) == AOP_LIT) {
4098     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4099         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4100         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4101         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4102   } else {
4103     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4104         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4105         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4106         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4107   }
4108         
4109   pic16_genMult32X32_32(left, right,result);
4110 }
4111
4112
4113
4114 /*-----------------------------------------------------------------*/
4115 /* genMult - generates code for multiplication                     */
4116 /*-----------------------------------------------------------------*/
4117 static void genMult (iCode *ic)
4118 {
4119   operand *left = IC_LEFT(ic);
4120   operand *right = IC_RIGHT(ic);
4121   operand *result= IC_RESULT(ic);   
4122
4123     FENTRY;
4124         /* assign the amsops */
4125         pic16_aopOp (left,ic,FALSE);
4126         pic16_aopOp (right,ic,FALSE);
4127         pic16_aopOp (result,ic,TRUE);
4128
4129         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4130
4131         /* special cases first *
4132         * both are bits */
4133         if (AOP_TYPE(left) == AOP_CRY
4134                 && AOP_TYPE(right)== AOP_CRY) {
4135                 genMultbits(left,right,result);
4136           goto release ;
4137         }
4138
4139         /* if both are of size == 1 */
4140         if(AOP_SIZE(left) == 1
4141                 && AOP_SIZE(right) == 1) {
4142                 genMultOneByte(left,right,result);
4143           goto release ;
4144         }
4145
4146         /* if both are of size == 2 */
4147         if(AOP_SIZE(left) == 2
4148                 && AOP_SIZE(right) == 2) {
4149                 genMultOneWord(left, right, result);
4150           goto release;
4151         }
4152         
4153         /* if both are of size == 4 */
4154         if(AOP_SIZE(left) == 4
4155                 && AOP_SIZE(right) == 4) {
4156                 genMultOneLong(left, right, result);
4157           goto release;
4158         }
4159         
4160         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4161
4162
4163         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4164         /* should have been converted to function call */
4165         assert(0) ;
4166
4167 release :
4168         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4169         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4170         pic16_freeAsmop(result,NULL,ic,TRUE); 
4171 }
4172
4173 /*-----------------------------------------------------------------*/
4174 /* genDivbits :- division of bits                                  */
4175 /*-----------------------------------------------------------------*/
4176 static void genDivbits (operand *left, 
4177                         operand *right, 
4178                         operand *result)
4179 {
4180   char *l;
4181
4182     FENTRY;
4183     /* the result must be bit */    
4184     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4185     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4186
4187     MOVA(l);    
4188
4189     pic16_emitcode("div","ab");
4190     pic16_emitcode("rrc","a");
4191     pic16_aopPut(AOP(result),"c",0);
4192 }
4193
4194 /*-----------------------------------------------------------------*/
4195 /* genDivOneByte : 8 bit division                                  */
4196 /*-----------------------------------------------------------------*/
4197 static void genDivOneByte (operand *left,
4198                            operand *right,
4199                            operand *result)
4200 {
4201   sym_link *opetype = operandType(result);
4202   char *l ;
4203   symbol *lbl ;
4204   int size,offset;
4205
4206         /* result = divident / divisor
4207          * - divident may be a register or a literal,
4208          * - divisor may be a register or a literal,
4209          * so there are 3 cases (literal / literal is optimized
4210          * by the front-end) to handle.
4211          * In addition we must handle signed and unsigned, which
4212          * result in 6 final different cases -- VR */
4213
4214     FENTRY;
4215     
4216     size = AOP_SIZE(result) - 1;
4217     offset = 1;
4218     /* signed or unsigned */
4219     if (SPEC_USIGN(opetype)) {
4220       pCodeOp *pct1,    /* count */
4221                 *pct2,  /* reste */
4222                 *pct3;  /* temp */
4223       symbol *label1, *label2, *label3;;
4224
4225
4226         /* unsigned is easy */
4227
4228         pct1 = pic16_popGetTempReg(1);
4229         pct2 = pic16_popGetTempReg(1);
4230         pct3 = pic16_popGetTempReg(1);
4231         
4232         label1 = newiTempLabel(NULL);
4233         label2 = newiTempLabel(NULL);
4234         label3 = newiTempLabel(NULL);
4235
4236         /* the following algorithm is extracted from divuint.c */
4237
4238         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4239         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4240         
4241         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4242
4243         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4244         
4245         pic16_emitpLabel(label1->key);
4246         
4247         emitCLRC;
4248         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4249
4250
4251         emitCLRC;
4252         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4253         
4254
4255         emitSKPNC;
4256         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4257         
4258         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4259         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4260         
4261         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4262         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4263         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4264         
4265         pic16_emitpLabel( label3->key );
4266         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4267         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4268         
4269         
4270
4271         pic16_emitpLabel(label2->key);
4272         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4273         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4274         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4275         
4276         /* result is in wreg */
4277         if(AOP_TYPE(result) != AOP_ACC)
4278                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4279
4280         pic16_popReleaseTempReg( pct3, 1);
4281         pic16_popReleaseTempReg( pct2, 1);
4282         pic16_popReleaseTempReg( pct1, 1);
4283
4284         return ;
4285     }
4286
4287     /* signed is a little bit more difficult */
4288
4289     /* save the signs of the operands */
4290     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4291     MOVA(l);    
4292     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4293     pic16_emitcode("push","acc"); /* save it on the stack */
4294
4295     /* now sign adjust for both left & right */
4296     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4297     MOVA(l);       
4298     lbl = newiTempLabel(NULL);
4299     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4300     pic16_emitcode("cpl","a");   
4301     pic16_emitcode("inc","a");
4302     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4303     pic16_emitcode("mov","b,a");
4304
4305     /* sign adjust left side */
4306     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4307     MOVA(l);
4308
4309     lbl = newiTempLabel(NULL);
4310     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4311     pic16_emitcode("cpl","a");
4312     pic16_emitcode("inc","a");
4313     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4314
4315     /* now the division */
4316     pic16_emitcode("div","ab");
4317     /* we are interested in the lower order
4318     only */
4319     pic16_emitcode("mov","b,a");
4320     lbl = newiTempLabel(NULL);
4321     pic16_emitcode("pop","acc");   
4322     /* if there was an over flow we don't 
4323     adjust the sign of the result */
4324     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4325     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4326     CLRC;
4327     pic16_emitcode("clr","a");
4328     pic16_emitcode("subb","a,b");
4329     pic16_emitcode("mov","b,a");
4330     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4331
4332     /* now we are done */
4333     pic16_aopPut(AOP(result),"b",0);
4334     if(size > 0){
4335         pic16_emitcode("mov","c,b.7");
4336         pic16_emitcode("subb","a,acc");   
4337     }
4338     while (size--)
4339         pic16_aopPut(AOP(result),"a",offset++);
4340
4341 }
4342
4343 /*-----------------------------------------------------------------*/
4344 /* genDiv - generates code for division                            */
4345 /*-----------------------------------------------------------------*/
4346 static void genDiv (iCode *ic)
4347 {
4348     operand *left = IC_LEFT(ic);
4349     operand *right = IC_RIGHT(ic);
4350     operand *result= IC_RESULT(ic);   
4351
4352
4353         /* Division is a very lengthy algorithm, so it is better
4354          * to call support routines than inlining algorithm.
4355          * Division functions written here just in case someone
4356          * wants to inline and not use the support libraries -- VR */
4357
4358     FENTRY;
4359     
4360     /* assign the amsops */
4361     pic16_aopOp (left,ic,FALSE);
4362     pic16_aopOp (right,ic,FALSE);
4363     pic16_aopOp (result,ic,TRUE);
4364
4365     /* special cases first */
4366     /* both are bits */
4367     if (AOP_TYPE(left) == AOP_CRY &&
4368         AOP_TYPE(right)== AOP_CRY) {
4369         genDivbits(left,right,result);
4370         goto release ;
4371     }
4372
4373     /* if both are of size == 1 */
4374     if (AOP_SIZE(left) == 1 &&
4375         AOP_SIZE(right) == 1 ) {
4376         genDivOneByte(left,right,result);
4377         goto release ;
4378     }
4379
4380     /* should have been converted to function call */
4381     assert(0);
4382 release :
4383     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385     pic16_freeAsmop(result,NULL,ic,TRUE); 
4386 }
4387
4388 /*-----------------------------------------------------------------*/
4389 /* genModbits :- modulus of bits                                   */
4390 /*-----------------------------------------------------------------*/
4391 static void genModbits (operand *left, 
4392                         operand *right, 
4393                         operand *result)
4394 {
4395   char *l;
4396
4397     FENTRY;  
4398     
4399     werror(W_POSSBUG2, __FILE__, __LINE__);
4400     /* the result must be bit */    
4401     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4403
4404     MOVA(l);       
4405
4406     pic16_emitcode("div","ab");
4407     pic16_emitcode("mov","a,b");
4408     pic16_emitcode("rrc","a");
4409     pic16_aopPut(AOP(result),"c",0);
4410 }
4411
4412 /*-----------------------------------------------------------------*/
4413 /* genModOneByte : 8 bit modulus                                   */
4414 /*-----------------------------------------------------------------*/
4415 static void genModOneByte (operand *left,
4416                            operand *right,
4417                            operand *result)
4418 {
4419   sym_link *opetype = operandType(result);
4420   char *l ;
4421   symbol *lbl ;
4422
4423     FENTRY;
4424     werror(W_POSSBUG2, __FILE__, __LINE__);
4425
4426     /* signed or unsigned */
4427     if (SPEC_USIGN(opetype)) {
4428         /* unsigned is easy */
4429         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4430         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4431         MOVA(l);    
4432         pic16_emitcode("div","ab");
4433         pic16_aopPut(AOP(result),"b",0);
4434         return ;
4435     }
4436
4437     /* signed is a little bit more difficult */
4438
4439     /* save the signs of the operands */
4440     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4441     MOVA(l);
4442
4443     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4444     pic16_emitcode("push","acc"); /* save it on the stack */
4445
4446     /* now sign adjust for both left & right */
4447     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4448     MOVA(l);
4449
4450     lbl = newiTempLabel(NULL);
4451     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4452     pic16_emitcode("cpl","a");   
4453     pic16_emitcode("inc","a");
4454     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4455     pic16_emitcode("mov","b,a"); 
4456
4457     /* sign adjust left side */
4458     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4459     MOVA(l);
4460
4461     lbl = newiTempLabel(NULL);
4462     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4463     pic16_emitcode("cpl","a");   
4464     pic16_emitcode("inc","a");
4465     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4466
4467     /* now the multiplication */
4468     pic16_emitcode("div","ab");
4469     /* we are interested in the lower order
4470     only */
4471     lbl = newiTempLabel(NULL);
4472     pic16_emitcode("pop","acc");   
4473     /* if there was an over flow we don't 
4474     adjust the sign of the result */
4475     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4476     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4477     CLRC ;
4478     pic16_emitcode("clr","a");
4479     pic16_emitcode("subb","a,b");
4480     pic16_emitcode("mov","b,a");
4481     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4482
4483     /* now we are done */
4484     pic16_aopPut(AOP(result),"b",0);
4485
4486 }
4487
4488 /*-----------------------------------------------------------------*/
4489 /* genMod - generates code for division                            */
4490 /*-----------------------------------------------------------------*/
4491 static void genMod (iCode *ic)
4492 {
4493   operand *left = IC_LEFT(ic);
4494   operand *right = IC_RIGHT(ic);
4495   operand *result= IC_RESULT(ic);  
4496
4497     FENTRY;
4498     
4499     /* assign the amsops */
4500     pic16_aopOp (left,ic,FALSE);
4501     pic16_aopOp (right,ic,FALSE);
4502     pic16_aopOp (result,ic,TRUE);
4503
4504     /* special cases first */
4505     /* both are bits */
4506     if (AOP_TYPE(left) == AOP_CRY &&
4507         AOP_TYPE(right)== AOP_CRY) {
4508         genModbits(left,right,result);
4509         goto release ;
4510     }
4511
4512     /* if both are of size == 1 */
4513     if (AOP_SIZE(left) == 1 &&
4514         AOP_SIZE(right) == 1 ) {
4515         genModOneByte(left,right,result);
4516         goto release ;
4517     }
4518
4519     /* should have been converted to function call */
4520     assert(0);
4521
4522 release :
4523     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4524     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4525     pic16_freeAsmop(result,NULL,ic,TRUE); 
4526 }
4527
4528 /*-----------------------------------------------------------------*/
4529 /* genIfxJump :- will create a jump depending on the ifx           */
4530 /*-----------------------------------------------------------------*/
4531 /*
4532   note: May need to add parameter to indicate when a variable is in bit space.
4533 */
4534 static void genIfxJump (iCode *ic, char *jval)
4535 {
4536   FENTRY;
4537   
4538     /* if true label then we jump if condition
4539     supplied is true */
4540     if ( IC_TRUE(ic) ) {
4541
4542         if(strcmp(jval,"a") == 0)
4543           emitSKPZ;
4544         else if (strcmp(jval,"c") == 0)
4545           emitSKPNC;
4546         else {
4547           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4548           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4549         }
4550
4551         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4552         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4553
4554     }
4555     else {
4556         /* false label is present */
4557         if(strcmp(jval,"a") == 0)
4558           emitSKPNZ;
4559         else if (strcmp(jval,"c") == 0)
4560           emitSKPC;
4561         else {
4562           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4563           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4564         }
4565
4566         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4567         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4568
4569     }
4570
4571
4572     /* mark the icode as generated */
4573     ic->generated = 1;
4574 }
4575
4576 #if 0
4577 // not needed ATM
4578
4579 /*-----------------------------------------------------------------*/
4580 /* genSkip                                                         */
4581 /*-----------------------------------------------------------------*/
4582 static void genSkip(iCode *ifx,int status_bit)
4583 {
4584   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4585   if(!ifx)
4586     return;
4587
4588   if ( IC_TRUE(ifx) ) {
4589     switch(status_bit) {
4590     case 'z':
4591       emitSKPNZ;
4592       break;
4593
4594     case 'c':
4595       emitSKPNC;
4596       break;
4597
4598     case 'd':
4599       emitSKPDC;
4600       break;
4601
4602     }
4603
4604     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4605     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4606
4607   } else {
4608
4609     switch(status_bit) {
4610
4611     case 'z':
4612       emitSKPZ;
4613       break;
4614
4615     case 'c':
4616       emitSKPC;
4617       break;
4618
4619     case 'd':
4620       emitSKPDC;
4621       break;
4622     }
4623     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4624     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4625
4626   }
4627
4628 }
4629 #endif
4630
4631 /*-----------------------------------------------------------------*/
4632 /* genSkipc                                                        */
4633 /*-----------------------------------------------------------------*/
4634 static void genSkipc(resolvedIfx *rifx)
4635 {
4636   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4637   
4638   if(!rifx)
4639     return;
4640
4641   if(rifx->condition)
4642     emitSKPC;
4643   else
4644     emitSKPNC;
4645
4646   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4647   rifx->generated = 1;
4648 }
4649
4650 #if !(USE_SIMPLE_GENCMP)
4651 /*-----------------------------------------------------------------*/
4652 /* genSkipz2                                                       */
4653 /*-----------------------------------------------------------------*/
4654 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4655 {
4656   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4657   
4658   if(!rifx)
4659     return;
4660
4661   if( (rifx->condition ^ invert_condition) & 1)
4662     emitSKPZ;
4663   else
4664     emitSKPNZ;
4665
4666   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4667   rifx->generated = 1;
4668 }
4669 #endif
4670
4671 #if 0
4672 /*-----------------------------------------------------------------*/
4673 /* genSkipz                                                        */
4674 /*-----------------------------------------------------------------*/
4675 static void genSkipz(iCode *ifx, int condition)
4676 {
4677   if(!ifx)
4678     return;
4679
4680   if(condition)
4681     emitSKPNZ;
4682   else
4683     emitSKPZ;
4684
4685   if ( IC_TRUE(ifx) )
4686     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4687   else
4688     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4689
4690   if ( IC_TRUE(ifx) )
4691     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4692   else
4693     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4694
4695 }
4696 #endif
4697
4698 #if !(USE_SIMPLE_GENCMP)
4699 /*-----------------------------------------------------------------*/
4700 /* genSkipCond                                                     */
4701 /*-----------------------------------------------------------------*/
4702 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4703 {
4704   if(!rifx)
4705     return;
4706
4707   if(rifx->condition)
4708     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4709   else
4710     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4711
4712
4713   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4714   rifx->generated = 1;
4715 }
4716 #endif
4717
4718 #if 0
4719 /*-----------------------------------------------------------------*/
4720 /* genChkZeroes :- greater or less than comparison                 */
4721 /*     For each byte in a literal that is zero, inclusive or the   */
4722 /*     the corresponding byte in the operand with W                */
4723 /*     returns true if any of the bytes are zero                   */
4724 /*-----------------------------------------------------------------*/
4725 static int genChkZeroes(operand *op, int lit,  int size)
4726 {
4727
4728   int i;
4729   int flag =1;
4730
4731   while(size--) {
4732     i = (lit >> (size*8)) & 0xff;
4733
4734     if(i==0) {
4735       if(flag) 
4736         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4737       else
4738         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4739       flag = 0;
4740     }
4741   }
4742
4743   return (flag==0);
4744 }
4745 #endif
4746
4747 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4748 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4749 #endif
4750 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4751 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4752
4753 /*-----------------------------------------------------------------*/
4754 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4755 /*                  aop (if it's NOT a literal) or from lit (if    */
4756 /*                  aop is a literal)                              */
4757 /*-----------------------------------------------------------------*/
4758 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4759   if (aop->type == AOP_LIT) {
4760     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4761   } else {
4762     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4763   }
4764 }
4765
4766 /*-----------------------------------------------------------------*/
4767 /* genCmp :- greater or less than comparison                       */
4768 /*-----------------------------------------------------------------*/
4769
4770 #if USE_SIMPLE_GENCMP
4771
4772 /* genCmp performs a left < right comparison, stores
4773  * the outcome in result (if != NULL) and generates
4774  * control flow code for the ifx (if != NULL).
4775  *
4776  * This version leaves in sequences like
4777  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4778  * which should be optmized by the peephole
4779  * optimizer - RN 2005-01-01 */
4780 static void genCmp (operand *left,operand *right,
4781                     operand *result, iCode *ifx, int sign)
4782 {
4783   resolvedIfx rIfx;
4784   int size;
4785   int offs;
4786   symbol *templbl;
4787   operand *dummy;
4788   unsigned long lit;
4789   unsigned long mask;
4790   int performedLt;
4791
4792   FENTRY;
4793   
4794   assert (AOP_SIZE(left) == AOP_SIZE(right));
4795   assert (left && right);
4796
4797   size = AOP_SIZE(right) - 1;
4798   mask = (0x100UL << (size*8)) - 1;
4799   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4800   performedLt = 1;
4801   templbl = NULL;
4802   lit = 0;
4803   
4804   resolveIfx (&rIfx, ifx);
4805
4806   /**********************************************************************
4807    * handle bits - bit compares are promoted to int compares seemingly! *
4808    **********************************************************************/
4809 #if 0
4810   // THIS IS COMPLETELY UNTESTED!
4811   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4812     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4813     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4814     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4815
4816     emitSETC;
4817     // 1 < {0,1} is false --> clear C by skipping the next instruction
4818     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4819     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4820     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4821     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4822     emitCLRC; // only skipped for left=0 && right=1
4823
4824     goto correct_result_in_carry;
4825   } // if
4826 #endif
4827
4828   /*************************************************
4829    * make sure that left is register (or the like) *
4830    *************************************************/
4831   if (!isAOP_REGlike(left)) {
4832     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4833     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4834     #endif
4835     assert (isAOP_LIT(left));
4836     assert (isAOP_REGlike(right));
4837     // swap left and right
4838     // left < right <==> right > left <==> (right >= left + 1)
4839     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4840
4841     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4842       // MAXVALUE < right? always false
4843       if (performedLt) emitCLRC; else emitSETC;
4844       goto correct_result_in_carry;
4845     } // if
4846
4847     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4848     // that's we handled it above.
4849     lit++;
4850
4851     dummy = left;
4852     left = right;
4853     right = dummy;
4854
4855     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4856   } else if (isAOP_LIT(right)) {
4857     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4858   } // if
4859
4860   assert (isAOP_REGlike(left)); // left must be register or the like
4861   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4862
4863   /*************************************************
4864    * special cases go here                         *
4865    *************************************************/
4866
4867   if (isAOP_LIT(right)) {
4868     if (!sign) {
4869       // unsigned comparison to a literal
4870       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4871       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4872       #endif
4873       if (lit == 0) {
4874         // unsigned left < 0? always false
4875         if (performedLt) emitCLRC; else emitSETC;
4876         goto correct_result_in_carry;
4877       }
4878     } else {
4879       // signed comparison to a literal
4880       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4881       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4882       #endif
4883       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4884         // signed left < 0x80000000? always false
4885         if (performedLt) emitCLRC; else emitSETC;
4886         goto correct_result_in_carry;
4887       } else if (lit == 0) {
4888         // compare left < 0; set CARRY if SIGNBIT(left) is set
4889         if (performedLt) emitSETC; else emitCLRC;
4890         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4891         if (performedLt) emitCLRC; else emitSETC;
4892         goto correct_result_in_carry;
4893       }
4894     } // if (!sign)
4895   } // right is literal
4896
4897   /*************************************************
4898    * perform a general case comparison             *
4899    * make sure we get CARRY==1 <==> left >= right  *
4900    *************************************************/
4901   // compare most significant bytes
4902   //DEBUGpc ("comparing bytes at offset %d", size);
4903   if (!sign) {
4904     // unsigned comparison
4905     mov2w_regOrLit (AOP(right), lit, size);
4906     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4907   } else {
4908     // signed comparison
4909     // (add 2^n to both operands then perform an unsigned comparison)
4910     if (isAOP_LIT(right)) {
4911       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4912       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4913
4914       if (litbyte == 0x80) {
4915         // left >= 0x80 -- always true, but more bytes to come
4916         pic16_mov2w (AOP(left), size);
4917         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4918         emitSETC;
4919       } else {
4920         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4921         pic16_mov2w (AOP(left), size);
4922         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4923         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4924       } // if
4925     } else {
4926       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4927       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4928       pic16_mov2w (AOP(left), size);
4929       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4930       pic16_emitpcode (POC_MOVWF, pctemp);
4931       pic16_mov2w (AOP(right), size);
4932       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4933       pic16_emitpcode (POC_SUBFW, pctemp);
4934       //pic16_popReleaseTempReg(pctemp, 1);
4935     }
4936   } // if (!sign)
4937
4938   // compare remaining bytes (treat as unsigned case from above)
4939   templbl = newiTempLabel ( NULL );
4940   offs = size;
4941   while (offs--) {
4942     //DEBUGpc ("comparing bytes at offset %d", offs);
4943     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4944     mov2w_regOrLit (AOP(right), lit, offs);
4945     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4946   } // while (offs)
4947   pic16_emitpLabel (templbl->key);
4948   goto result_in_carry;
4949
4950 result_in_carry:
4951   
4952   /****************************************************
4953    * now CARRY contains the result of the comparison: *
4954    * SUBWF sets CARRY iff                             *
4955    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4956    * (F=left, W=right)
4957    ****************************************************/
4958
4959   if (performedLt) {
4960     if (result && AOP_TYPE(result) != AOP_CRY) {
4961       // value will be stored
4962       emitTOGC;
4963     } else {
4964       // value wil only be used in the following genSkipc()
4965       rIfx.condition ^= 1;
4966     }
4967   } // if
4968
4969 correct_result_in_carry:
4970
4971   // assign result to variable (if neccessary)
4972   if (result && AOP_TYPE(result) != AOP_CRY) {
4973     //DEBUGpc ("assign result");
4974     size = AOP_SIZE(result);
4975     while (size--) {
4976       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4977     } // while
4978     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4979   } // if (result)
4980
4981   // perform conditional jump
4982   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4983   if (ifx) {
4984     //DEBUGpc ("generate control flow");
4985     rIfx.condition ^= 1;
4986     genSkipc (&rIfx);
4987     ifx->generated = 1;
4988   } // if
4989 }
4990
4991 #elif 1
4992                 /* { */
4993       /* original code */
4994 static void genCmp (operand *left,operand *right,
4995                     operand *result, iCode *ifx, int sign)
4996 {
4997   int size; //, offset = 0 ;
4998   unsigned long lit = 0L,i = 0;
4999   resolvedIfx rFalseIfx;
5000   //  resolvedIfx rTrueIfx;
5001   symbol *truelbl;
5002   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5003 /*
5004   if(ifx) {
5005     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5006     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5007   }
5008 */
5009
5010   FENTRY;
5011   
5012   resolveIfx(&rFalseIfx,ifx);
5013   truelbl  = newiTempLabel(NULL);
5014   size = max(AOP_SIZE(left),AOP_SIZE(right));
5015
5016   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5017
5018 #define _swapp
5019
5020   /* if literal is on the right then swap with left */
5021   if ((AOP_TYPE(right) == AOP_LIT)) {
5022     operand *tmp = right ;
5023     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5024     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5025 #ifdef _swapp
5026
5027     lit = (lit - 1) & mask;
5028     right = left;
5029     left = tmp;
5030     rFalseIfx.condition ^= 1;
5031 #endif
5032
5033   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5034     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5035   }
5036
5037
5038   //if(IC_TRUE(ifx) == NULL)
5039   /* if left & right are bit variables */
5040   if (AOP_TYPE(left) == AOP_CRY &&
5041       AOP_TYPE(right) == AOP_CRY ) {
5042     assert (0 && "bit variables used in genCmp");
5043     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5044     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5045   } else {
5046     /* subtract right from left if at the
5047        end the carry flag is set then we know that
5048        left is greater than right */
5049
5050     symbol *lbl  = newiTempLabel(NULL);
5051
5052 #if 0
5053         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5054                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5055 #endif
5056
5057 #ifndef _swapp
5058     if(AOP_TYPE(right) == AOP_LIT) {
5059
5060       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5061
5062       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5063
5064       /* special cases */
5065
5066       if(lit == 0) {
5067
5068         if(sign != 0) 
5069           genSkipCond(&rFalseIfx,left,size-1,7);
5070         else 
5071           /* no need to compare to 0...*/
5072           /* NOTE: this is a de-generate compare that most certainly 
5073            *       creates some dead code. */
5074           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5075
5076         if(ifx) ifx->generated = 1;
5077         return;
5078
5079       }
5080       size--;
5081
5082       if(size == 0) {
5083         //i = (lit >> (size*8)) & 0xff;
5084         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5085         
5086         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5087
5088         i = ((0-lit) & 0xff);
5089         if(sign) {
5090           if( i == 0x81) { 
5091             /* lit is 0x7f, all signed chars are less than
5092              * this except for 0x7f itself */
5093             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5094             genSkipz2(&rFalseIfx,0);
5095           } else {
5096             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5097             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5098             genSkipc(&rFalseIfx);
5099           }
5100
5101         } else {
5102           if(lit == 1) {
5103             genSkipz2(&rFalseIfx,1);
5104           } else {
5105             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5106             genSkipc(&rFalseIfx);
5107           }
5108         }
5109
5110         if(ifx) ifx->generated = 1;
5111         return;
5112       }
5113
5114       /* chars are out of the way. now do ints and longs */
5115
5116
5117       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5118         
5119       /* special cases */
5120
5121       if(sign) {
5122
5123         if(lit == 0) {
5124           genSkipCond(&rFalseIfx,left,size,7);
5125           if(ifx) ifx->generated = 1;
5126           return;
5127         }
5128
5129         if(lit <0x100) {
5130           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5131
5132           //rFalseIfx.condition ^= 1;
5133           //genSkipCond(&rFalseIfx,left,size,7);
5134           //rFalseIfx.condition ^= 1;
5135
5136           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5137           if(rFalseIfx.condition)
5138             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5139           else
5140             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5141
5142           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5143           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5144           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5145
5146           while(size > 1)
5147             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5148
5149           if(rFalseIfx.condition) {
5150             emitSKPZ;
5151             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5152
5153           } else {
5154             emitSKPNZ;
5155           }
5156
5157           genSkipc(&rFalseIfx);
5158           pic16_emitpLabel(truelbl->key);
5159           if(ifx) ifx->generated = 1;
5160           return;
5161
5162         }
5163
5164         if(size == 1) {
5165
5166           if( (lit & 0xff) == 0) {
5167             /* lower byte is zero */
5168             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5169             i = ((lit >> 8) & 0xff) ^0x80;
5170             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5171             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5172             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5173             genSkipc(&rFalseIfx);
5174
5175
5176             if(ifx) ifx->generated = 1;
5177             return;
5178
5179           }
5180         } else {
5181           /* Special cases for signed longs */
5182           if( (lit & 0xffffff) == 0) {
5183             /* lower byte is zero */
5184             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5185             i = ((lit >> 8*3) & 0xff) ^0x80;
5186             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5187             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5188             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5189             genSkipc(&rFalseIfx);
5190
5191
5192             if(ifx) ifx->generated = 1;
5193             return;
5194
5195           }
5196
5197         }
5198
5199
5200         if(lit & (0x80 << (size*8))) {
5201           /* lit is negative */
5202           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5203
5204           //genSkipCond(&rFalseIfx,left,size,7);
5205
5206           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5207
5208           if(rFalseIfx.condition)
5209             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5210           else
5211             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5212
5213
5214         } else {
5215           /* lit is positive */
5216           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5217           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5218           if(rFalseIfx.condition)
5219             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5220           else
5221             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5222
5223         }
5224
5225         /*
5226           This works, but is only good for ints.
5227           It also requires a "known zero" register.
5228           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5229           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5230           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5231           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5232           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5233           genSkipc(&rFalseIfx);
5234
5235           pic16_emitpLabel(truelbl->key);
5236           if(ifx) ifx->generated = 1;
5237           return;
5238         **/
5239           
5240         /* There are no more special cases, so perform a general compare */
5241   
5242         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5243         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5244
5245         while(size--) {
5246
5247           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5248           emitSKPNZ;
5249           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5250         }
5251         //rFalseIfx.condition ^= 1;
5252         genSkipc(&rFalseIfx);
5253
5254         pic16_emitpLabel(truelbl->key);
5255
5256         if(ifx) ifx->generated = 1;
5257         return;
5258
5259
5260       }
5261
5262
5263       /* sign is out of the way. So now do an unsigned compare */
5264       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5265
5266
5267       /* General case - compare to an unsigned literal on the right.*/
5268
5269       i = (lit >> (size*8)) & 0xff;
5270       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5271       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5272       while(size--) {
5273         i = (lit >> (size*8)) & 0xff;
5274
5275         if(i) {
5276           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5277           emitSKPNZ;
5278           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5279         } else {
5280           /* this byte of the lit is zero, 
5281            *if it's not the last then OR in the variable */
5282           if(size)
5283             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5284         }
5285       }
5286
5287
5288       pic16_emitpLabel(lbl->key);
5289 //      pic16_emitpLabel(truelbl->key);
5290       //if(emitFinalCheck)
5291       genSkipc(&rFalseIfx);
5292       if(sign)
5293         pic16_emitpLabel(truelbl->key);
5294
5295       if(ifx) ifx->generated = 1;
5296       return;
5297
5298
5299     }
5300 #endif  // _swapp
5301
5302     if(AOP_TYPE(left) == AOP_LIT) {
5303       //symbol *lbl = newiTempLabel(NULL);
5304
5305       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5306
5307
5308       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5309
5310       /* Special cases */
5311       if((lit == 0) && (sign == 0)){
5312
5313         size--;
5314         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5315         while(size) 
5316           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5317
5318         genSkipz2(&rFalseIfx,0);
5319         if(ifx) ifx->generated = 1;
5320         return;
5321       }
5322
5323       if(size==1) {
5324         /* Special cases */
5325         lit &= 0xff;
5326         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5327           /* degenerate compare can never be true */
5328           if(rFalseIfx.condition == 0)
5329             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5330
5331           if(ifx) ifx->generated = 1;
5332           return;
5333         }
5334
5335         if(sign) {
5336           /* signed comparisons to a literal byte */
5337
5338           int lp1 = (lit+1) & 0xff;
5339
5340           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5341           switch (lp1) {
5342           case 0:
5343             rFalseIfx.condition ^= 1;
5344             genSkipCond(&rFalseIfx,right,0,7);
5345             break;
5346           case 0x7f:
5347             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5348             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5349             genSkipz2(&rFalseIfx,1);
5350             break;
5351           default:
5352             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5353             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5354             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5355             rFalseIfx.condition ^= 1;
5356             genSkipc(&rFalseIfx);
5357             break;
5358           }
5359         } else {
5360           /* unsigned comparisons to a literal byte */
5361
5362           switch(lit & 0xff ) {
5363           case 0:
5364             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5365             genSkipz2(&rFalseIfx,0);
5366             break;
5367           case 0x7f:
5368             rFalseIfx.condition ^= 1;
5369             genSkipCond(&rFalseIfx,right,0,7);
5370             break;
5371
5372           default:
5373             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5374             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5375             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5376             rFalseIfx.condition ^= 1;
5377             if (AOP_TYPE(result) == AOP_CRY)
5378               genSkipc(&rFalseIfx);
5379             else {
5380               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5381               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5382             }         
5383             break;
5384           }
5385         }
5386
5387         if(ifx) ifx->generated = 1;
5388         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5389                 goto check_carry;
5390         return;
5391
5392       } else {
5393
5394         /* Size is greater than 1 */
5395
5396         if(sign) {
5397           int lp1 = lit+1;
5398
5399           size--;
5400
5401           if(lp1 == 0) {
5402             /* this means lit = 0xffffffff, or -1 */
5403
5404
5405             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5406             rFalseIfx.condition ^= 1;
5407             genSkipCond(&rFalseIfx,right,size,7);
5408             if(ifx) ifx->generated = 1;
5409
5410             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5411               goto check_carry;
5412
5413             return;
5414           }
5415
5416           if(lit == 0) {
5417             int s = size;
5418
5419             if(rFalseIfx.condition) {
5420               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5422             }
5423
5424             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5425             while(size--)
5426               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5427
5428
5429             emitSKPZ;
5430             if(rFalseIfx.condition) {
5431               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5432               pic16_emitpLabel(truelbl->key);
5433             }else {
5434               rFalseIfx.condition ^= 1;
5435               genSkipCond(&rFalseIfx,right,s,7);
5436             }
5437
5438             if(ifx) ifx->generated = 1;
5439
5440             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5441               goto check_carry;
5442
5443             return;
5444           }
5445
5446           if((size == 1) &&  (0 == (lp1&0xff))) {
5447             /* lower byte of signed word is zero */
5448             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5449             i = ((lp1 >> 8) & 0xff) ^0x80;
5450             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5451             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5452             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5453
5454             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5455               emitTOGC;
5456               if(ifx) ifx->generated = 1;
5457               goto check_carry;
5458             } else {
5459               rFalseIfx.condition ^= 1;
5460               genSkipc(&rFalseIfx);
5461               if(ifx) ifx->generated = 1;
5462             }
5463
5464             return;
5465           }
5466
5467           if(lit & (0x80 << (size*8))) {
5468             /* Lit is less than zero */
5469             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5470             //rFalseIfx.condition ^= 1;
5471             //genSkipCond(&rFalseIfx,left,size,7);
5472             //rFalseIfx.condition ^= 1;
5473             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5474             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5475
5476             if(rFalseIfx.condition)
5477               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5478             else
5479               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5480
5481
5482           } else {
5483             /* Lit is greater than or equal to zero */
5484             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5485             //rFalseIfx.condition ^= 1;
5486             //genSkipCond(&rFalseIfx,right,size,7);
5487             //rFalseIfx.condition ^= 1;
5488
5489             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5490             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5491
5492             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5493             if(rFalseIfx.condition)
5494               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5495             else
5496               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5497
5498           }
5499
5500           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5501           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5502
5503           while(size--) {
5504
5505             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5506             emitSKPNZ;
5507             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5508           }
5509           rFalseIfx.condition ^= 1;
5510           //rFalseIfx.condition = 1;
5511           genSkipc(&rFalseIfx);
5512
5513           pic16_emitpLabel(truelbl->key);
5514
5515           if(ifx) ifx->generated = 1;
5516
5517
5518           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5519             goto check_carry;
5520
5521           return;
5522           // end of if (sign)
5523         } else {
5524
5525           /* compare word or long to an unsigned literal on the right.*/
5526
5527
5528           size--;
5529           if(lit < 0xff) {
5530             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5531             switch (lit) {
5532             case 0:
5533               break; /* handled above */
5534 /*
5535             case 0xff:
5536               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5537               while(size--)
5538                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5539               genSkipz2(&rFalseIfx,0);
5540               break;
5541 */
5542             default:
5543               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5544               while(--size)
5545                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5546
5547               emitSKPZ;
5548               if(rFalseIfx.condition)
5549                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5550               else
5551                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5552
5553
5554               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5555               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5556
5557               rFalseIfx.condition ^= 1;
5558               genSkipc(&rFalseIfx);
5559             }
5560
5561             pic16_emitpLabel(truelbl->key);
5562
5563             if(ifx) ifx->generated = 1;
5564
5565             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5566               goto check_carry;
5567
5568             return;
5569           }
5570
5571
5572           lit++;
5573           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5574           i = (lit >> (size*8)) & 0xff;
5575
5576           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5577           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5578
5579           while(size--) {
5580             i = (lit >> (size*8)) & 0xff;
5581
5582             if(i) {
5583               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5584               emitSKPNZ;
5585               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5586             } else {
5587               /* this byte of the lit is zero, 
5588                * if it's not the last then OR in the variable */
5589               if(size)
5590                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5591             }
5592           }
5593
5594
5595           pic16_emitpLabel(lbl->key);
5596
5597           rFalseIfx.condition ^= 1;
5598
5599           genSkipc(&rFalseIfx);
5600         }
5601
5602         if(sign)
5603           pic16_emitpLabel(truelbl->key);
5604         if(ifx) ifx->generated = 1;
5605
5606             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5607               goto check_carry;
5608
5609         return;
5610       }
5611     }
5612     /* Compare two variables */
5613
5614     DEBUGpic16_emitcode(";sign","%d",sign);
5615
5616     size--;
5617     if(sign) {
5618       /* Sigh. thus sucks... */
5619       if(size) {
5620         pCodeOp *pctemp;
5621         
5622         pctemp = pic16_popGetTempReg(1);
5623         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5624         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5625         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5626         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5627         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5628         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5629         pic16_popReleaseTempReg(pctemp, 1);
5630       } else {
5631         /* Signed char comparison */
5632         /* Special thanks to Nikolai Golovchenko for this snippet */
5633         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5634         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5635         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5636         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5637         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5638         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5639
5640         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5641         genSkipc(&rFalseIfx);
5642           
5643         if(ifx) ifx->generated = 1;
5644
5645             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5646               goto check_carry;
5647
5648         return;
5649       }
5650
5651     } else {
5652
5653       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5655     }
5656
5657
5658     /* The rest of the bytes of a multi-byte compare */
5659     while (size) {
5660
5661       emitSKPZ;
5662       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5663       size--;
5664
5665       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5666       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5667
5668
5669     }
5670
5671     pic16_emitpLabel(lbl->key);
5672
5673     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5674     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5675         (AOP_TYPE(result) == AOP_REG)) {
5676       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5677       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5678     } else {
5679       genSkipc(&rFalseIfx);
5680     }         
5681     //genSkipc(&rFalseIfx);
5682     if(ifx) ifx->generated = 1;
5683
5684
5685             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5686               goto check_carry;
5687
5688     return;
5689
5690   }
5691
5692 check_carry:
5693   if ((AOP_TYPE(result) != AOP_CRY) 
5694         && AOP_SIZE(result)) {
5695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5696
5697     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5698
5699     pic16_outBitC(result);
5700   } else {
5701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5702     /* if the result is used in the next
5703        ifx conditional branch then generate
5704        code a little differently */
5705     if (ifx )
5706       genIfxJump (ifx,"c");
5707     else
5708       pic16_outBitC(result);
5709     /* leave the result in acc */
5710   }
5711
5712 }
5713
5714 #else   /* old version of genCmp() */   /* } else { */
5715
5716 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5717 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5718         operand *result, int offset, int invert_op)
5719 {
5720   /* add code here */
5721   
5722   /* check condition, > or < ?? */
5723   if(rIfx->condition != 0)invert_op ^= 1;
5724   
5725   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5726
5727   if(!ifx)invert_op ^= 1;
5728
5729   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5730       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5731   
5732   /* do selection */
5733   if(!invert_op)return POC_CPFSGT;
5734   else return POC_CPFSLT;
5735 }
5736
5737 static int compareAopfirstpass=1;
5738
5739 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5740             operand *oper, int offset, operand *result,
5741             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5742             symbol *tlbl)
5743 {
5744   int op;
5745   symbol *truelbl;
5746
5747   /* invert if there is a result to be loaded, in order to fit,
5748    * SETC/CLRC sequence */
5749   if(AOP_SIZE(result))invert_op ^= 1;
5750
5751 //  if(sign && !offset)invert_op ^= 1;
5752   
5753 //  if(sign)invert_op ^= 1;
5754   
5755   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5756
5757   if(AOP_SIZE(result) && compareAopfirstpass) {
5758     if(!ifx) {
5759       if(pcop2)
5760         pic16_emitpcode(POC_SETF, pcop2);
5761       else
5762         emitSETC;
5763     } else {
5764       if(pcop2)
5765         pic16_emitpcode(POC_CLRF, pcop2);
5766       else
5767         emitCLRC;
5768     }
5769   }
5770
5771   compareAopfirstpass = 0;
5772
5773       /* there is a bug when comparing operands with size > 1,
5774        * because higher bytes can be equal and test should be performed
5775        * to the next lower byte, current algorithm, considers operands
5776        * inequal in these cases! -- VR 20041107 */
5777
5778     
5779   if(pcop)
5780     pic16_emitpcode(op, pcop);
5781   else
5782     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5783
5784
5785   if((!sign || !offset) && AOP_SIZE(result)) {
5786     if(!ifx) {
5787       if(pcop2)
5788         pic16_emitpcode(POC_CLRF, pcop2);
5789         else
5790         emitCLRC;
5791     } else {
5792       if(pcop2)
5793         pic16_emitpcode(POC_SETF, pcop2);
5794       else
5795         emitSETC;
5796     }
5797     
5798     /* don't emit final branch (offset == 0) */
5799     if(offset) {
5800
5801       if(pcop2)
5802         pic16_emitpcode(POC_RRCF, pcop2);
5803
5804       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5805     }
5806   } else {
5807     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5808       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5809             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5810
5811       truelbl = newiTempLabel( NULL );
5812       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5813       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5814         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5815       else
5816         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5817       pic16_emitpLabel(truelbl->key);
5818     } else {
5819       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5820     }
5821   }
5822 }
5823
5824
5825   
5826
5827 #if 1   /* { */
5828 static void genCmp (operand *left, operand *right,
5829                     operand *result, iCode *ifx, int sign)
5830 {
5831   int size, cmpop=1;
5832   long lit = 0L;
5833   resolvedIfx rFalseIfx;
5834   symbol *falselbl, *tlbl;
5835
5836     FENTRY;
5837     
5838     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5839
5840     resolveIfx(&rFalseIfx, ifx);
5841     size = max(AOP_SIZE(left), AOP_SIZE(right));
5842     
5843     /* if left & right are bit variables */
5844     if(AOP_TYPE(left) == AOP_CRY
5845       && AOP_TYPE(right) == AOP_CRY ) {
5846
5847         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5848         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5849         
5850         werror(W_POSSBUG2, __FILE__, __LINE__);
5851         exit(-1);
5852     }
5853     
5854     /* if literal is on the right then swap with left */
5855     if((AOP_TYPE(right) == AOP_LIT)) {
5856       operand *tmp = right ;
5857 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5858
5859         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5860
5861 //      lit = (lit - 1) & mask;
5862         right = left;
5863         left = tmp;
5864         rFalseIfx.condition ^= 1;               /* reverse compare */
5865     } else
5866     if ((AOP_TYPE(left) == AOP_LIT)) {
5867       /* float compares are handled by support functions */
5868       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5869     }
5870
5871     /* actual comparing algorithm */
5872 //    size = AOP_SIZE( right );
5873
5874     falselbl = newiTempLabel( NULL );
5875     if(AOP_TYPE(left) == AOP_LIT) {
5876       /* compare to literal */
5877       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5878       
5879       if(sign) {
5880         pCodeOp *pct, *pct2;
5881         symbol *tlbl1;
5882
5883         /* signed compare */
5884         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5885
5886         pct = pic16_popCopyReg(&pic16_pc_prodl);
5887         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5888         tlbl = newiTempLabel( NULL );
5889         
5890         /* first compare signs:
5891          *  a. if both are positive, compare just like unsigned
5892          *  b. if both are negative, invert cmpop, compare just like unsigned
5893          *  c. if different signs, determine the result directly */
5894
5895         size--;
5896
5897 #if 1
5898         /* { */
5899         tlbl1 = newiTempLabel( NULL );
5900 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5901
5902         if(lit > 0) {
5903
5904           /* literal is zero or positive:
5905            *  a. if carry is zero, too, continue compare,
5906            *  b. if carry is set, then continue depending on cmpop ^ condition:
5907            *    1. '<' return false (literal < variable),
5908            *    2. '>' return true (literal > variable) */
5909 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5910           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5911           
5912           
5913           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5914           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5915         } else 
5916         if(lit < 0) {
5917           
5918           /* literal is negative:
5919            *  a. if carry is set, too, continue compare,
5920            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5921            *    1. '<' return true (literal < variable),
5922            *    2. '>' return false (literal > variable) */
5923 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5924           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5925           
5926           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5927           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5928         }
5929 #if 1
5930         else {
5931           /* lit == 0 */
5932           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5933           
5934           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5935           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5936         }
5937 #endif
5938         
5939         
5940         pic16_emitpLabel( tlbl1->key );
5941 #endif  /* } */
5942
5943         compareAopfirstpass=1;
5944 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5945 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5946 //        pic16_emitpcode(POC_MOVWF, pct);
5947
5948 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5949         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5950 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5951         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5952
5953         /* generic case */        
5954           while( size-- ) {
5955 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5956 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5957 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5958 //            pic16_emitpcode(POC_MOVWF, pct);
5959
5960 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5961             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5962             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5963 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5964 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5965           }
5966 //        }
5967         
5968         if(ifx)ifx->generated = 1;
5969
5970         if(AOP_SIZE(result)) {
5971           pic16_emitpLabel(tlbl->key);
5972           pic16_emitpLabel(falselbl->key);
5973           pic16_outBitOp( result, pct2 );
5974         } else {
5975           pic16_emitpLabel(tlbl->key);
5976         }
5977       } else {
5978
5979
5980         /* unsigned compare */      
5981         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5982     
5983         compareAopfirstpass=1;
5984         while(size--) {
5985           
5986           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5987           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5988
5989         }
5990
5991         if(ifx)ifx->generated = 1;
5992
5993
5994         if(AOP_SIZE(result)) {
5995           pic16_emitpLabel(falselbl->key);
5996           pic16_outBitC( result );
5997         }
5998
5999       }
6000     } else {
6001       /* compare registers */
6002       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6003
6004
6005       if(sign) {
6006         pCodeOp *pct, *pct2;
6007         
6008         /* signed compare */
6009         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6010
6011         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6012         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6013         tlbl = newiTempLabel( NULL );
6014         
6015         compareAopfirstpass=1;
6016
6017         size--;
6018         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6019 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6020         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6021         pic16_emitpcode(POC_MOVWF, pct);
6022
6023         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6024 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6025         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6026
6027         /* WREG already holds left + 0x80 */
6028         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6029         
6030         while( size-- ) {
6031           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6032 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6033           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6034           pic16_emitpcode(POC_MOVWF, pct);
6035                 
6036           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6037 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6038           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6039
6040           /* WREG already holds left + 0x80 */
6041           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6042 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6043         }
6044         
6045         if(ifx)ifx->generated = 1;
6046
6047         if(AOP_SIZE(result)) {
6048           pic16_emitpLabel(tlbl->key);
6049           pic16_emitpLabel(falselbl->key);
6050           pic16_outBitOp( result, pct2 );
6051         } else {
6052           pic16_emitpLabel(tlbl->key);
6053         }
6054
6055       } else {
6056         /* unsigned compare */      
6057         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6058
6059         compareAopfirstpass=1;
6060         while(size--) {
6061           
6062           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6063           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6064
6065         }
6066
6067         if(ifx)ifx->generated = 1;
6068         if(AOP_SIZE(result)) {
6069
6070           pic16_emitpLabel(falselbl->key);
6071           pic16_outBitC( result );
6072         }
6073
6074       }
6075     }
6076 }
6077
6078 #else    /* } else { */
6079
6080 /* new version of genCmp -- VR 20041012 */
6081 static void genCmp (operand *left,operand *right,
6082                     operand *result, iCode *ifx, int sign)
6083 {
6084   int size; //, offset = 0 ;
6085   unsigned long lit = 0L,i = 0;
6086   resolvedIfx rFalseIfx;
6087   int willCheckCarry=0;
6088   //  resolvedIfx rTrueIfx;
6089   symbol *truelbl;
6090
6091     FENTRY;
6092   
6093   /* General concept:
6094    * subtract right from left if at the end the carry flag is set then we
6095    * know that left is greater than right */
6096             
6097   resolveIfx(&rFalseIfx,ifx);
6098   truelbl  = newiTempLabel(NULL);
6099   size = max(AOP_SIZE(left),AOP_SIZE(right));
6100
6101   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6102
6103   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6104    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6105   
6106
6107   /* if literal is on the right then swap with left */
6108   if ((AOP_TYPE(right) == AOP_LIT)) {
6109     operand *tmp = right ;
6110     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6111
6112       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6113
6114 //      lit = (lit - 1) & mask;
6115       right = left;
6116       left = tmp;
6117       rFalseIfx.condition ^= 1;         /* reverse compare */
6118   } else
6119   if ((AOP_TYPE(left) == AOP_LIT)) {
6120     /* float compares are handled by support functions */
6121     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6122   }
6123
6124
6125   //if(IC_TRUE(ifx) == NULL)
6126   /* if left & right are bit variables */
6127   if (AOP_TYPE(left) == AOP_CRY &&
6128       AOP_TYPE(right) == AOP_CRY ) {
6129
6130     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6131     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6132
6133   } else {
6134     symbol *lbl  = newiTempLabel(NULL);
6135
6136     if(AOP_TYPE(left) == AOP_LIT) {
6137       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6138
6139       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6140         willCheckCarry = 1;
6141       else willCheckCarry = 0;
6142
6143       /* Special cases */
6144       if((lit == 0) && (sign == 0)) {
6145         /* unsigned compare to 0 */
6146         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6147         
6148         size--;
6149         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6150         while(size) 
6151           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6152
6153         genSkipz2(&rFalseIfx,0);
6154         if(ifx)ifx->generated = 1;
6155         return;
6156       }
6157
6158       if(size==1) {
6159         /* Special cases */
6160         lit &= 0xff;
6161         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6162           /* degenerate compare can never be true */
6163           if(rFalseIfx.condition == 0)
6164             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6165
6166           if(ifx) ifx->generated = 1;
6167           return;
6168         }
6169
6170         if(sign) {
6171           /* signed comparisons to a literal byte */
6172           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6173
6174           int lp1 = (lit+1) & 0xff;
6175
6176           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6177           switch (lp1) {
6178           case 0:
6179             rFalseIfx.condition ^= 1;
6180             genSkipCond(&rFalseIfx,right,0,7);
6181             break;
6182           case 0x7f:
6183             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6184             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6185             genSkipz2(&rFalseIfx,1);
6186             break;
6187           default:
6188             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6189             
6190             if(rFalseIfx.condition)
6191               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6192             else
6193               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6194
6195             if(willCheckCarry) {
6196               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6197               else { emitSETC; emitCLRC; }
6198               
6199             } else {
6200               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6201             }              
6202                       
6203 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6204             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6206             rFalseIfx.condition ^= 1;
6207             genSkipc(&rFalseIfx);
6208 */
6209             break;
6210           }
6211         } else {
6212           /* unsigned comparisons to a literal byte */
6213           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6214
6215           switch(lit & 0xff ) {
6216                           /* special cases */
6217           case 0:
6218             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6219             genSkipz2(&rFalseIfx,0);
6220             break;
6221           case 0x7f:
6222             rFalseIfx.condition ^= 1;
6223             genSkipCond(&rFalseIfx,right,0,7);
6224             break;
6225           default:
6226             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6227             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6228             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6229             rFalseIfx.condition ^= 1;
6230             if (AOP_TYPE(result) == AOP_CRY)
6231               genSkipc(&rFalseIfx);
6232             else {
6233               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6234               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6235             }         
6236             break;
6237           }
6238         }
6239
6240         if(ifx) ifx->generated = 1;
6241         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6242                 goto check_carry;
6243         return;
6244
6245       } else {
6246
6247         /* Size is greater than 1 */
6248
6249         if(sign) {
6250           int lp1 = lit+1;
6251
6252           size--;
6253
6254           if(lp1 == 0) {
6255             /* this means lit = 0xffffffff, or -1 */
6256
6257
6258             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6259             rFalseIfx.condition ^= 1;
6260             genSkipCond(&rFalseIfx,right,size,7);
6261             if(ifx) ifx->generated = 1;
6262             return;
6263           }
6264
6265           if(lit == 0) {
6266             int s = size;
6267
6268             if(rFalseIfx.condition) {
6269               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6270               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6271             }
6272
6273             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6274             while(size--)
6275               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6276
6277
6278             emitSKPZ;
6279             if(rFalseIfx.condition) {
6280               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6281               pic16_emitpLabel(truelbl->key);
6282             }else {
6283               rFalseIfx.condition ^= 1;
6284               genSkipCond(&rFalseIfx,right,s,7);
6285             }
6286
6287             if(ifx) ifx->generated = 1;
6288             return;
6289           }
6290
6291           if((size == 1) &&  (0 == (lp1&0xff))) {
6292             /* lower byte of signed word is zero */
6293             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6294             i = ((lp1 >> 8) & 0xff) ^0x80;
6295             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6297             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6298             rFalseIfx.condition ^= 1;
6299             genSkipc(&rFalseIfx);
6300
6301
6302             if(ifx) ifx->generated = 1;
6303             return;
6304           }
6305
6306           if(lit & (0x80 << (size*8))) {
6307             /* Lit is less than zero */
6308             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6309             //rFalseIfx.condition ^= 1;
6310             //genSkipCond(&rFalseIfx,left,size,7);
6311             //rFalseIfx.condition ^= 1;
6312             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6313             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6314
6315             if(rFalseIfx.condition)
6316               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6317             else
6318               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6319
6320
6321           } else {
6322             /* Lit is greater than or equal to zero */
6323             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6324             //rFalseIfx.condition ^= 1;
6325             //genSkipCond(&rFalseIfx,right,size,7);
6326             //rFalseIfx.condition ^= 1;
6327
6328             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6329             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6330
6331             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6332             if(rFalseIfx.condition)
6333               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6334             else
6335               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6336
6337           }
6338
6339
6340           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6341           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6342
6343           while(size--) {
6344
6345             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6346             emitSKPNZ;
6347             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6348           }
6349           rFalseIfx.condition ^= 1;
6350           //rFalseIfx.condition = 1;
6351           genSkipc(&rFalseIfx);
6352
6353           pic16_emitpLabel(truelbl->key);
6354
6355           if(ifx) ifx->generated = 1;
6356           return;
6357           // end of if (sign)
6358         } else {
6359
6360           /* compare word or long to an unsigned literal on the right.*/
6361
6362
6363           size--;
6364           if(lit < 0xff) {
6365             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6366             switch (lit) {
6367             case 0:
6368               break; /* handled above */
6369 /*
6370             case 0xff:
6371               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6372               while(size--)
6373                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6374               genSkipz2(&rFalseIfx,0);
6375               break;
6376 */
6377             default:
6378               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6379               while(--size)
6380                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6381
6382               emitSKPZ;
6383               if(rFalseIfx.condition)
6384                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6385               else
6386                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6387
6388
6389               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6390               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6391
6392               rFalseIfx.condition ^= 1;
6393               genSkipc(&rFalseIfx);
6394             }
6395
6396             pic16_emitpLabel(truelbl->key);
6397
6398             if(ifx) ifx->generated = 1;
6399             return;
6400           }
6401
6402
6403           lit++;
6404           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6405           i = (lit >> (size*8)) & 0xff;
6406
6407           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6408           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6409
6410           while(size--) {
6411             i = (lit >> (size*8)) & 0xff;
6412
6413             if(i) {
6414               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6415               emitSKPNZ;
6416               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6417             } else {
6418               /* this byte of the lit is zero, 
6419                * if it's not the last then OR in the variable */
6420               if(size)
6421                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6422             }
6423           }
6424
6425
6426           pic16_emitpLabel(lbl->key);
6427
6428           rFalseIfx.condition ^= 1;
6429
6430           genSkipc(&rFalseIfx);
6431         }
6432
6433         if(sign)
6434           pic16_emitpLabel(truelbl->key);
6435         if(ifx) ifx->generated = 1;
6436         return;
6437       }
6438     }
6439     /* Compare two variables */
6440
6441     DEBUGpic16_emitcode(";sign","%d",sign);
6442
6443     size--;
6444     if(sign) {
6445       /* Sigh. thus sucks... */
6446       if(size) {
6447         pCodeOp *pctemp;
6448         
6449         pctemp = pic16_popGetTempReg(1);
6450         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6451         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6452         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6453         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6454         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6455         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6456         pic16_popReleaseTempReg(pctemp, 1);
6457       } else {
6458         /* Signed char comparison */
6459         /* Special thanks to Nikolai Golovchenko for this snippet */
6460         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6461         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6462         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6463         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6464         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6465         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466
6467         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6468         genSkipc(&rFalseIfx);
6469           
6470         if(ifx) ifx->generated = 1;
6471         return;
6472       }
6473
6474     } else {
6475
6476       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6477       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6478     }
6479
6480
6481     /* The rest of the bytes of a multi-byte compare */
6482     while (size) {
6483
6484       emitSKPZ;
6485       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6486       size--;
6487
6488       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6489       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6490
6491
6492     }
6493
6494     pic16_emitpLabel(lbl->key);
6495
6496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6497     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6498         (AOP_TYPE(result) == AOP_REG)) {
6499       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6500       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6501     } else {
6502       genSkipc(&rFalseIfx);
6503     }         
6504     //genSkipc(&rFalseIfx);
6505     if(ifx) ifx->generated = 1;
6506
6507     return;
6508
6509   }
6510
6511 check_carry:
6512   if ((AOP_TYPE(result) != AOP_CRY) 
6513         && AOP_SIZE(result)) {
6514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6515
6516     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6517
6518     pic16_outBitC(result);
6519   } else {
6520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6521     /* if the result is used in the next
6522        ifx conditional branch then generate
6523        code a little differently */
6524     if (ifx )
6525       genIfxJump (ifx,"c");
6526     else
6527       pic16_outBitC(result);
6528     /* leave the result in acc */
6529   }
6530
6531 }
6532 #endif  /* } */
6533
6534
6535 #endif  /* } */
6536
6537
6538
6539 /*-----------------------------------------------------------------*/
6540 /* genCmpGt :- greater than comparison                             */
6541 /*-----------------------------------------------------------------*/
6542 static void genCmpGt (iCode *ic, iCode *ifx)
6543 {
6544   operand *left, *right, *result;
6545   sym_link *letype , *retype;
6546   int sign ;
6547
6548     FENTRY;
6549     
6550     left = IC_LEFT(ic);
6551     right= IC_RIGHT(ic);
6552     result = IC_RESULT(ic);
6553
6554     letype = getSpec(operandType(left));
6555     retype =getSpec(operandType(right));
6556     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6557     /* assign the amsops */
6558     pic16_aopOp (left,ic,FALSE);
6559     pic16_aopOp (right,ic,FALSE);
6560     pic16_aopOp (result,ic,TRUE);
6561
6562     genCmp(right, left, result, ifx, sign);
6563
6564     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6565     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6566     pic16_freeAsmop(result,NULL,ic,TRUE); 
6567 }
6568
6569 /*-----------------------------------------------------------------*/
6570 /* genCmpLt - less than comparisons                                */
6571 /*-----------------------------------------------------------------*/
6572 static void genCmpLt (iCode *ic, iCode *ifx)
6573 {
6574   operand *left, *right, *result;
6575   sym_link *letype , *retype;
6576   int sign ;
6577
6578     FENTRY;
6579
6580     left = IC_LEFT(ic);
6581     right= IC_RIGHT(ic);
6582     result = IC_RESULT(ic);
6583
6584     letype = getSpec(operandType(left));
6585     retype =getSpec(operandType(right));
6586     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6587
6588     /* assign the amsops */
6589     pic16_aopOp (left,ic,FALSE);
6590     pic16_aopOp (right,ic,FALSE);
6591     pic16_aopOp (result,ic,TRUE);
6592
6593     genCmp(left, right, result, ifx, sign);
6594
6595     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6596     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6597     pic16_freeAsmop(result,NULL,ic,TRUE); 
6598 }
6599
6600 #if 0
6601 // not needed ATM
6602 // FIXME reenable literal optimisation when the pic16 port is stable
6603
6604 /*-----------------------------------------------------------------*/
6605 /* genc16bit2lit - compare a 16 bit value to a literal             */
6606 /*-----------------------------------------------------------------*/
6607 static void genc16bit2lit(operand *op, int lit, int offset)
6608 {
6609   int i;
6610
6611   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6612   if( (lit&0xff) == 0) 
6613     i=1;
6614   else
6615     i=0;
6616
6617   switch( BYTEofLONG(lit,i)) { 
6618   case 0:
6619     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6620     break;
6621   case 1:
6622     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6623     break;
6624   case 0xff:
6625     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6626     break;
6627   default:
6628     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6629     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6630   }
6631
6632   i ^= 1;
6633
6634   switch( BYTEofLONG(lit,i)) { 
6635   case 0:
6636     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6637     break;
6638   case 1:
6639     emitSKPNZ;
6640     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6641     break;
6642   case 0xff:
6643     emitSKPNZ;
6644     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6645     break;
6646   default:
6647     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6648     emitSKPNZ;
6649     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6650
6651   }
6652
6653 }
6654 #endif
6655
6656 #if 0
6657 // not needed ATM
6658 /*-----------------------------------------------------------------*/
6659 /* gencjneshort - compare and jump if not equal                    */
6660 /*-----------------------------------------------------------------*/
6661 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6662 {
6663   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6664   int offset = 0;
6665   int res_offset = 0;  /* the result may be a different size then left or right */
6666   int res_size = AOP_SIZE(result);
6667   resolvedIfx rIfx;
6668   symbol *lbl, *lbl_done;
6669
6670   unsigned long lit = 0L;
6671   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6672
6673   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6674   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6675   if(result)
6676     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6677   resolveIfx(&rIfx,ifx);
6678   lbl =  newiTempLabel(NULL);
6679   lbl_done =  newiTempLabel(NULL);
6680
6681
6682   /* if the left side is a literal or 
6683      if the right is in a pointer register and left 
6684      is not */
6685   if ((AOP_TYPE(left) == AOP_LIT) || 
6686       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6687     operand *t = right;
6688     right = left;
6689     left = t;
6690   }
6691   if(AOP_TYPE(right) == AOP_LIT)
6692     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6693
6694   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6695     preserve_result = 1;
6696
6697   if(result && !preserve_result)
6698     {
6699       int i;
6700       for(i = 0; i < AOP_SIZE(result); i++)
6701         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6702     }
6703
6704
6705   /* if the right side is a literal then anything goes */
6706   if (AOP_TYPE(right) == AOP_LIT &&
6707       AOP_TYPE(left) != AOP_DIR ) {
6708     switch(size) {
6709     case 2:
6710       genc16bit2lit(left, lit, 0);
6711       emitSKPZ;
6712       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6713       break;
6714     default:
6715       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6716       while (size--) {
6717         if(lit & 0xff) {
6718           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6719           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6720         } else {
6721           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6722         }
6723
6724         emitSKPZ;
6725         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6726         offset++;
6727         if(res_offset < res_size-1)
6728           res_offset++;
6729         lit >>= 8;
6730       }
6731       break;
6732     }
6733   }
6734
6735   /* if the right side is in a register or in direct space or
6736      if the left is a pointer register & right is not */    
6737   else if (AOP_TYPE(right) == AOP_REG ||
6738            AOP_TYPE(right) == AOP_DIR || 
6739            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6740            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6741     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6742     int lbl_key = lbl->key;
6743
6744     if(result) {
6745       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6746       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6747     }else {
6748       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6749       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6750               __FUNCTION__,__LINE__);
6751       return;
6752     }
6753    
6754 /*     switch(size) { */
6755 /*     case 2: */
6756 /*       genc16bit2lit(left, lit, 0); */
6757 /*       emitSKPNZ; */
6758 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6759 /*       break; */
6760 /*     default: */
6761     while (size--) {
6762       int emit_skip=1;
6763       if((AOP_TYPE(left) == AOP_DIR) && 
6764          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6765
6766         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6767         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6768
6769       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6770             
6771         switch (lit & 0xff) {
6772         case 0:
6773           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774           break;
6775         case 1:
6776           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6777           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6778           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6779           emit_skip=0;
6780           break;
6781         case 0xff:
6782           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6783           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6784           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6785           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6786           emit_skip=0;
6787           break;
6788         default:
6789           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6790           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6791         }
6792         lit >>= 8;
6793
6794       } else {
6795         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6796       }
6797       if(emit_skip) {
6798         if(AOP_TYPE(result) == AOP_CRY) {
6799           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6800           if(rIfx.condition)
6801             emitSKPNZ;
6802           else
6803             emitSKPZ;
6804           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6805         } else {
6806           /* fix me. probably need to check result size too */
6807           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6808           if(rIfx.condition)
6809             emitSKPZ;
6810           else
6811             emitSKPNZ;
6812           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6813           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6814         }
6815         if(ifx)
6816           ifx->generated=1;
6817       }
6818       emit_skip++;
6819       offset++;
6820       if(res_offset < res_size-1)
6821         res_offset++;
6822     }
6823 /*       break; */
6824 /*     } */
6825   } else if(AOP_TYPE(right) == AOP_REG &&
6826             AOP_TYPE(left) != AOP_DIR){
6827
6828     while(size--) {
6829       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6830       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6831       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6832       if(rIfx.condition)
6833         emitSKPNZ;
6834       else
6835         emitSKPZ;
6836       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6837       offset++;
6838       if(res_offset < res_size-1)
6839         res_offset++;
6840     }
6841       
6842   }else{
6843     /* right is a pointer reg need both a & b */
6844     while(size--) {
6845       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6846       if(strcmp(l,"b"))
6847         pic16_emitcode("mov","b,%s",l);
6848       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6849       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6850       offset++;
6851     }
6852   }
6853
6854   if(result && preserve_result)
6855     {
6856       int i;
6857       for(i = 0; i < AOP_SIZE(result); i++)
6858         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6859     }
6860
6861   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6862
6863   if(result && preserve_result)
6864     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6865
6866   if(!rIfx.condition)
6867     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6868
6869   pic16_emitpLabel(lbl->key);
6870
6871   if(result && preserve_result)
6872     {
6873       int i;
6874       for(i = 0; i < AOP_SIZE(result); i++)
6875         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6876
6877       pic16_emitpLabel(lbl_done->key);
6878    }
6879
6880   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6881
6882   if(ifx)
6883     ifx->generated = 1;
6884 }
6885 #endif
6886
6887 #if 0
6888 /*-----------------------------------------------------------------*/
6889 /* gencjne - compare and jump if not equal                         */
6890 /*-----------------------------------------------------------------*/
6891 static void gencjne(operand *left, operand *right, iCode *ifx)
6892 {
6893     symbol *tlbl  = newiTempLabel(NULL);
6894
6895     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6896     gencjneshort(left, right, lbl);
6897
6898     pic16_emitcode("mov","a,%s",one);
6899     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6900     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6901     pic16_emitcode("clr","a");
6902     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6903
6904     pic16_emitpLabel(lbl->key);
6905     pic16_emitpLabel(tlbl->key);
6906
6907 }
6908 #endif
6909
6910
6911 /*-----------------------------------------------------------------*/
6912 /* is_LitOp - check if operand has to be treated as literal        */
6913 /*-----------------------------------------------------------------*/
6914 static bool is_LitOp(operand *op)
6915 {
6916   return ((AOP_TYPE(op) == AOP_LIT)
6917       || ( (AOP_TYPE(op) == AOP_PCODE)
6918           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6919               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6920 }
6921
6922 /*-----------------------------------------------------------------*/
6923 /* is_LitAOp - check if operand has to be treated as literal        */
6924 /*-----------------------------------------------------------------*/
6925 static bool is_LitAOp(asmop *aop)
6926 {
6927   return ((aop->type == AOP_LIT)
6928       || ( (aop->type == AOP_PCODE)
6929           && ( (aop->aopu.pcop->type == PO_LITERAL)
6930               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6931 }
6932
6933
6934
6935 /*-----------------------------------------------------------------*/
6936 /* genCmpEq - generates code for equal to                          */
6937 /*-----------------------------------------------------------------*/
6938 static void genCmpEq (iCode *ic, iCode *ifx)
6939 {
6940   operand *left, *right, *result;
6941   symbol *falselbl = newiTempLabel(NULL);
6942   symbol *donelbl = newiTempLabel(NULL);
6943
6944   int preserve_result = 0;
6945   int generate_result = 0;
6946   int i=0;
6947
6948   FENTRY;
6949   
6950   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6951   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6952   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6953  
6954   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6955
6956   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6957     {
6958       werror(W_POSSBUG2, __FILE__, __LINE__);
6959       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6960       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6961       goto release;
6962     }
6963
6964   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6965     {
6966       operand *tmp = right ;
6967       right = left;
6968       left = tmp;
6969     }
6970
6971   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6972     preserve_result = 1;
6973
6974   if(result && AOP_SIZE(result))
6975     generate_result = 1;
6976
6977   if(generate_result && !preserve_result)
6978     {
6979       for(i = 0; i < AOP_SIZE(result); i++)
6980         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6981     }
6982
6983   for(i=0; i < AOP_SIZE(left); i++)
6984     {
6985       if(AOP_TYPE(left) != AOP_ACC)
6986         {
6987           if(is_LitOp(left))
6988             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6989           else
6990             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6991         }
6992       if(is_LitOp(right))
6993         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6994       else
6995         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6996
6997       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6998     }
6999
7000   // result == true
7001
7002   if(generate_result && preserve_result)
7003     {
7004       for(i = 0; i < AOP_SIZE(result); i++)
7005         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7006     }
7007
7008   if(generate_result)
7009     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7010
7011   if(generate_result && preserve_result)
7012     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7013
7014   if(ifx && IC_TRUE(ifx))
7015     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7016
7017   if(ifx && IC_FALSE(ifx))
7018     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7019
7020   pic16_emitpLabel(falselbl->key);
7021
7022   // result == false
7023
7024   if(ifx && IC_FALSE(ifx))
7025     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7026
7027   if(generate_result && preserve_result)
7028     {
7029       for(i = 0; i < AOP_SIZE(result); i++)
7030         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7031     }
7032
7033   pic16_emitpLabel(donelbl->key);
7034
7035   if(ifx)
7036     ifx->generated = 1;
7037
7038 release:
7039   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7040   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7041   pic16_freeAsmop(result,NULL,ic,TRUE);
7042
7043 }
7044
7045
7046 #if 0
7047 // old version kept for reference
7048
7049 /*-----------------------------------------------------------------*/
7050 /* genCmpEq - generates code for equal to                          */
7051 /*-----------------------------------------------------------------*/
7052 static void genCmpEq (iCode *ic, iCode *ifx)
7053 {
7054     operand *left, *right, *result;
7055     unsigned long lit = 0L;
7056     int size,offset=0;
7057     symbol *falselbl  = newiTempLabel(NULL);
7058
7059
7060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7061
7062     if(ifx)
7063       DEBUGpic16_emitcode ("; ifx is non-null","");
7064     else
7065       DEBUGpic16_emitcode ("; ifx is null","");
7066
7067     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7068     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7069     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7070
7071     size = max(AOP_SIZE(left),AOP_SIZE(right));
7072
7073     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7074
7075     /* if literal, literal on the right or 
7076     if the right is in a pointer register and left 
7077     is not */
7078     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7079         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7080       operand *tmp = right ;
7081       right = left;
7082       left = tmp;
7083     }
7084
7085
7086     if(ifx && !AOP_SIZE(result)){
7087         symbol *tlbl;
7088         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7089         /* if they are both bit variables */
7090         if (AOP_TYPE(left) == AOP_CRY &&
7091             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7092                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7093             if(AOP_TYPE(right) == AOP_LIT){
7094                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7095                 if(lit == 0L){
7096                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7097                     pic16_emitcode("cpl","c");
7098                 } else if(lit == 1L) {
7099                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7100                 } else {
7101                     pic16_emitcode("clr","c");
7102                 }
7103                 /* AOP_TYPE(right) == AOP_CRY */
7104             } else {
7105                 symbol *lbl = newiTempLabel(NULL);
7106                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7107                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7108                 pic16_emitcode("cpl","c");
7109                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7110             }
7111             /* if true label then we jump if condition
7112             supplied is true */
7113             tlbl = newiTempLabel(NULL);
7114             if ( IC_TRUE(ifx) ) {
7115                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7116                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7117             } else {
7118                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7119                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7120             }
7121             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7122
7123                 {
7124                 /* left and right are both bit variables, result is carry */
7125                         resolvedIfx rIfx;
7126               
7127                         resolveIfx(&rIfx,ifx);
7128
7129                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7130                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7131                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7132                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7133                         genSkipz2(&rIfx,0);
7134                 }
7135         } else {
7136
7137                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7138
7139                         /* They're not both bit variables. Is the right a literal? */
7140                         if(AOP_TYPE(right) == AOP_LIT) {
7141                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7142             
7143                         switch(size) {
7144
7145                                 case 1:
7146                                         switch(lit & 0xff) {
7147                                                 case 1:
7148                                                                 if ( IC_TRUE(ifx) ) {
7149                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7150                                                                         emitSKPNZ;
7151                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7152                                                                 } else {
7153                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7154                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7155                                                                 }
7156                                                                 break;
7157                                                 case 0xff:
7158                                                                 if ( IC_TRUE(ifx) ) {
7159                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7160                                                                         emitSKPNZ;
7161                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7162                                                                 } else {
7163                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7164                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7165                                                                 }
7166                                                                 break;
7167                                                 default:
7168                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7169                                                                 if(lit)
7170                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7171                                                                 genSkip(ifx,'z');
7172                                         } // switch lit
7173
7174
7175                                         /* end of size == 1 */
7176                                         break;
7177               
7178                                 case 2:
7179                                         genc16bit2lit(left,lit,offset);
7180                                         genSkip(ifx,'z');
7181                                         break;
7182                                         /* end of size == 2 */
7183
7184                                 default:
7185                                         /* size is 4 */
7186                                         if(lit==0) {
7187                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7188                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7189                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7190                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7191                                                 genSkip(ifx,'z');
7192                                         } else {
7193                                                 /* search for patterns that can be optimized */
7194
7195                                                 genc16bit2lit(left,lit,0);
7196                                                 lit >>= 16;
7197                                                 if(lit) {
7198                                                                 if(IC_TRUE(ifx))
7199                                                                 emitSKPZ; // if hi word unequal
7200                                                                 else
7201                                                                 emitSKPNZ; // if hi word equal
7202                                                                 // fail early
7203                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7204                                                         genc16bit2lit(left,lit,2);
7205                                                         genSkip(ifx,'z');
7206                                                 } else {
7207                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7208                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7209                                                         genSkip(ifx,'z');
7210                                                 }
7211                                         }
7212                                                 pic16_emitpLabel(falselbl->key);
7213                                                 break;
7214
7215                         } // switch size
7216           
7217                         ifx->generated = 1;
7218                         goto release ;
7219             
7220
7221           } else if(AOP_TYPE(right) == AOP_CRY ) {
7222             /* we know the left is not a bit, but that the right is */
7223             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7224             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7225                       pic16_popGet(AOP(right),offset));
7226             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7227
7228             /* if the two are equal, then W will be 0 and the Z bit is set
7229              * we could test Z now, or go ahead and check the high order bytes if
7230              * the variable we're comparing is larger than a byte. */
7231
7232             while(--size)
7233               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7234
7235             if ( IC_TRUE(ifx) ) {
7236               emitSKPNZ;
7237               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7238               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7239             } else {
7240               emitSKPZ;
7241               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7242               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7243             }
7244
7245           } else {
7246             /* They're both variables that are larger than bits */
7247             int s = size;
7248
7249             tlbl = newiTempLabel(NULL);
7250
7251             while(size--) {
7252               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7253               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7254
7255               if ( IC_TRUE(ifx) ) {
7256                 if(size) {
7257                   emitSKPZ;
7258                 
7259                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7260
7261                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7262                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7263                 } else {
7264                   emitSKPNZ;
7265
7266                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7267
7268
7269                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7270                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7271                 }
7272               } else {
7273                 emitSKPZ;
7274
7275                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7276
7277                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7278                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7279               }
7280               offset++;
7281             }
7282             if(s>1 && IC_TRUE(ifx)) {
7283               pic16_emitpLabel(tlbl->key);
7284               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7285             }
7286           }
7287         }
7288         /* mark the icode as generated */
7289         ifx->generated = 1;
7290         goto release ;
7291     }
7292
7293     /* if they are both bit variables */
7294     if (AOP_TYPE(left) == AOP_CRY &&
7295         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7296         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7297         if(AOP_TYPE(right) == AOP_LIT){
7298             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7299             if(lit == 0L){
7300                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7301                 pic16_emitcode("cpl","c");
7302             } else if(lit == 1L) {
7303                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7304             } else {
7305                 pic16_emitcode("clr","c");
7306             }
7307             /* AOP_TYPE(right) == AOP_CRY */
7308         } else {
7309             symbol *lbl = newiTempLabel(NULL);
7310             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7311             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7312             pic16_emitcode("cpl","c");
7313             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7314         }
7315         /* c = 1 if egal */
7316         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7317             pic16_outBitC(result);
7318             goto release ;
7319         }
7320         if (ifx) {
7321             genIfxJump (ifx,"c");
7322             goto release ;
7323         }
7324         /* if the result is used in an arithmetic operation
7325         then put the result in place */
7326         pic16_outBitC(result);
7327     } else {
7328       
7329       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7330       gencjne(left,right,result,ifx);
7331 /*
7332       if(ifx) 
7333         gencjne(left,right,newiTempLabel(NULL));
7334       else {
7335         if(IC_TRUE(ifx)->key)
7336           gencjne(left,right,IC_TRUE(ifx)->key);
7337         else
7338           gencjne(left,right,IC_FALSE(ifx)->key);
7339         ifx->generated = 1;
7340         goto release ;
7341       }
7342       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7343         pic16_aopPut(AOP(result),"a",0);
7344         goto release ;
7345       }
7346
7347       if (ifx) {
7348         genIfxJump (ifx,"a");
7349         goto release ;
7350       }
7351 */
7352       /* if the result is used in an arithmetic operation
7353          then put the result in place */
7354 /*
7355       if (AOP_TYPE(result) != AOP_CRY) 
7356         pic16_outAcc(result);
7357 */
7358       /* leave the result in acc */
7359     }
7360
7361 release:
7362     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7363     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7364     pic16_freeAsmop(result,NULL,ic,TRUE);
7365 }
7366 #endif
7367
7368 /*-----------------------------------------------------------------*/
7369 /* ifxForOp - returns the icode containing the ifx for operand     */
7370 /*-----------------------------------------------------------------*/
7371 static iCode *ifxForOp ( operand *op, iCode *ic )
7372 {
7373   FENTRY2;
7374
7375     /* if true symbol then needs to be assigned */
7376     if (IS_TRUE_SYMOP(op))
7377         return NULL ;
7378
7379     /* if this has register type condition and
7380     the next instruction is ifx with the same operand
7381     and live to of the operand is upto the ifx only then */
7382     if (ic->next
7383         && ic->next->op == IFX
7384         && IC_COND(ic->next)->key == op->key
7385         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7386         ) {
7387                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7388           return ic->next;
7389     }
7390
7391     /*
7392     if (ic->next &&
7393         ic->next->op == IFX &&
7394         IC_COND(ic->next)->key == op->key) {
7395       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7396       return ic->next;
7397     }
7398     */
7399
7400     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7401     if (ic->next &&
7402         ic->next->op == IFX)
7403       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7404
7405     if (ic->next &&
7406         ic->next->op == IFX &&
7407         IC_COND(ic->next)->key == op->key) {
7408       DEBUGpic16_emitcode ("; "," key is okay");
7409       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7410                            OP_SYMBOL(op)->liveTo,
7411                            ic->next->seq);
7412     }
7413
7414 #if 0
7415     /* the code below is completely untested
7416      * it just allows ulong2fs.c compile -- VR */
7417          
7418     ic = ic->next;
7419     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7420                                         __FILE__, __FUNCTION__, __LINE__);
7421         
7422     /* if this has register type condition and
7423     the next instruction is ifx with the same operand
7424     and live to of the operand is upto the ifx only then */
7425     if (ic->next &&
7426         ic->next->op == IFX &&
7427         IC_COND(ic->next)->key == op->key &&
7428         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7429         return ic->next;
7430
7431     if (ic->next &&
7432         ic->next->op == IFX &&
7433         IC_COND(ic->next)->key == op->key) {
7434       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7435       return ic->next;
7436     }
7437
7438     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7439                                         __FILE__, __FUNCTION__, __LINE__);
7440
7441 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7442 #endif
7443
7444     return NULL;
7445 }
7446 /*-----------------------------------------------------------------*/
7447 /* genAndOp - for && operation                                     */
7448 /*-----------------------------------------------------------------*/
7449 static void genAndOp (iCode *ic)
7450 {
7451   operand *left,*right, *result;
7452 /*     symbol *tlbl; */
7453
7454     FENTRY;
7455
7456     /* note here that && operations that are in an
7457     if statement are taken away by backPatchLabels
7458     only those used in arthmetic operations remain */
7459     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7460     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7461     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7462
7463     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7464
7465     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7466     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7467     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7468
7469     /* if both are bit variables */
7470 /*     if (AOP_TYPE(left) == AOP_CRY && */
7471 /*         AOP_TYPE(right) == AOP_CRY ) { */
7472 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7473 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7474 /*         pic16_outBitC(result); */
7475 /*     } else { */
7476 /*         tlbl = newiTempLabel(NULL); */
7477 /*         pic16_toBoolean(left);     */
7478 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7479 /*         pic16_toBoolean(right); */
7480 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7481 /*         pic16_outBitAcc(result); */
7482 /*     } */
7483
7484     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7485     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7486     pic16_freeAsmop(result,NULL,ic,TRUE);
7487 }
7488
7489
7490 /*-----------------------------------------------------------------*/
7491 /* genOrOp - for || operation                                      */
7492 /*-----------------------------------------------------------------*/
7493 /*
7494   tsd pic port -
7495   modified this code, but it doesn't appear to ever get called
7496 */
7497
7498 static void genOrOp (iCode *ic)
7499 {
7500   operand *left,*right, *result;
7501   symbol *tlbl;
7502
7503     FENTRY;  
7504
7505   /* note here that || operations that are in an
7506     if statement are taken away by backPatchLabels
7507     only those used in arthmetic operations remain */
7508     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7509     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7510     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7511
7512     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7513
7514     /* if both are bit variables */
7515     if (AOP_TYPE(left) == AOP_CRY &&
7516         AOP_TYPE(right) == AOP_CRY ) {
7517       pic16_emitcode("clrc","");
7518       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7519                AOP(left)->aopu.aop_dir,
7520                AOP(left)->aopu.aop_dir);
7521       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7522                AOP(right)->aopu.aop_dir,
7523                AOP(right)->aopu.aop_dir);
7524       pic16_emitcode("setc","");
7525
7526     } else {
7527         tlbl = newiTempLabel(NULL);
7528         pic16_toBoolean(left);
7529         emitSKPZ;
7530         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7531         pic16_toBoolean(right);
7532         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7533
7534         pic16_outBitAcc(result);
7535     }
7536
7537     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7538     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7539     pic16_freeAsmop(result,NULL,ic,TRUE);            
7540 }
7541
7542 /*-----------------------------------------------------------------*/
7543 /* isLiteralBit - test if lit == 2^n                               */
7544 /*-----------------------------------------------------------------*/
7545 static int isLiteralBit(unsigned long lit)
7546 {
7547     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7548     0x100L,0x200L,0x400L,0x800L,
7549     0x1000L,0x2000L,0x4000L,0x8000L,
7550     0x10000L,0x20000L,0x40000L,0x80000L,
7551     0x100000L,0x200000L,0x400000L,0x800000L,
7552     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7553     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7554     int idx;
7555     
7556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7557     for(idx = 0; idx < 32; idx++)
7558         if(lit == pw[idx])
7559             return idx+1;
7560     return 0;
7561 }
7562
7563 /*-----------------------------------------------------------------*/
7564 /* continueIfTrue -                                                */
7565 /*-----------------------------------------------------------------*/
7566 static void continueIfTrue (iCode *ic)
7567 {
7568   FENTRY;
7569   if(IC_TRUE(ic))
7570     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7571   ic->generated = 1;
7572 }
7573
7574 /*-----------------------------------------------------------------*/
7575 /* jmpIfTrue -                                                     */
7576 /*-----------------------------------------------------------------*/
7577 static void jumpIfTrue (iCode *ic)
7578 {
7579   FENTRY;
7580   if(!IC_TRUE(ic))
7581     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7582   ic->generated = 1;
7583 }
7584
7585 /*-----------------------------------------------------------------*/
7586 /* jmpTrueOrFalse -                                                */
7587 /*-----------------------------------------------------------------*/
7588 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7589 {
7590   // ugly but optimized by peephole
7591   FENTRY;
7592   if(IC_TRUE(ic)){
7593     symbol *nlbl = newiTempLabel(NULL);
7594       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7595       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7596       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7597       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7598   } else {
7599     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7600     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7601   }
7602   ic->generated = 1;
7603 }
7604
7605 /*-----------------------------------------------------------------*/
7606 /* genAnd  - code for and                                          */
7607 /*-----------------------------------------------------------------*/
7608 static void genAnd (iCode *ic, iCode *ifx)
7609 {
7610   operand *left, *right, *result;
7611   int size, offset=0;  
7612   unsigned long lit = 0L;
7613   int bytelit = 0;
7614   resolvedIfx rIfx;
7615
7616     FENTRY;
7617     
7618   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7619   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7620   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7621
7622   resolveIfx(&rIfx,ifx);
7623
7624   /* if left is a literal & right is not then exchange them */
7625   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7626       AOP_NEEDSACC(left)) {
7627     operand *tmp = right ;
7628     right = left;
7629     left = tmp;
7630   }
7631
7632   /* if result = right then exchange them */
7633   if(pic16_sameRegs(AOP(result),AOP(right))){
7634     operand *tmp = right ;
7635     right = left;
7636     left = tmp;
7637   }
7638
7639   /* if right is bit then exchange them */
7640   if (AOP_TYPE(right) == AOP_CRY &&
7641       AOP_TYPE(left) != AOP_CRY){
7642     operand *tmp = right ;
7643     right = left;
7644     left = tmp;
7645   }
7646   if(AOP_TYPE(right) == AOP_LIT)
7647     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7648
7649   size = AOP_SIZE(result);
7650
7651   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7652
7653   // if(bit & yy)
7654   // result = bit & yy;
7655   if (AOP_TYPE(left) == AOP_CRY){
7656     // c = bit & literal;
7657     if(AOP_TYPE(right) == AOP_LIT){
7658       if(lit & 1) {
7659         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7660           // no change
7661           goto release;
7662         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7663       } else {
7664         // bit(result) = 0;
7665         if(size && (AOP_TYPE(result) == AOP_CRY)){
7666           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7667           goto release;
7668         }
7669         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7670           jumpIfTrue(ifx);
7671           goto release;
7672         }
7673         pic16_emitcode("clr","c");
7674       }
7675     } else {
7676       if (AOP_TYPE(right) == AOP_CRY){
7677         // c = bit & bit;
7678         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7679         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7680       } else {
7681         // c = bit & val;
7682         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7683         // c = lsb
7684         pic16_emitcode("rrc","a");
7685         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7686       }
7687     }
7688     // bit = c
7689     // val = c
7690     if(size)
7691       pic16_outBitC(result);
7692     // if(bit & ...)
7693     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7694       genIfxJump(ifx, "c");           
7695     goto release ;
7696   }
7697
7698   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7699   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7700   if((AOP_TYPE(right) == AOP_LIT) &&
7701      (AOP_TYPE(result) == AOP_CRY) &&
7702      (AOP_TYPE(left) != AOP_CRY)){
7703     int posbit = isLiteralBit(lit);
7704     /* left &  2^n */
7705     if(posbit){
7706       posbit--;
7707       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7708       // bit = left & 2^n
7709       if(size)
7710         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7711       // if(left &  2^n)
7712       else{
7713         if(ifx){
7714 /*
7715           if(IC_TRUE(ifx)) {
7716             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7717             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7718           } else {
7719             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7720             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7721           }
7722 */
7723         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7724         size = AOP_SIZE(left);
7725
7726         {
7727           int bp = posbit, ofs=0;
7728           
7729             while(bp > 7) {
7730               bp -= 8;
7731               ofs++;
7732             }
7733         
7734           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7735                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7736
7737         }
7738 /*
7739           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7740                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7741 */
7742           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7743           
7744           ifx->generated = 1;
7745         }
7746         goto release;
7747       }
7748     } else {
7749       symbol *tlbl = newiTempLabel(NULL);
7750       int sizel = AOP_SIZE(left);
7751
7752       if(size)
7753         emitSETC;
7754
7755       while(sizel--) {
7756         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7757
7758           /* patch provided by Aaron Colwell */
7759           if((posbit = isLiteralBit(bytelit)) != 0) {
7760               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7761                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7762                                                 (posbit-1),0, PO_GPR_REGISTER));
7763
7764               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7765 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7766           } else {
7767               if (bytelit == 0xff) {
7768                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7769                    * a peephole could optimize it out -- VR */
7770                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7771               } else {
7772                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7773                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7774               }
7775
7776               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7777                             pic16_popGetLabel(tlbl->key));
7778           }
7779         
7780 #if 0
7781           /* old code, left here for reference -- VR 09/2004 */
7782           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7783           // byte ==  2^n ?
7784           if((posbit = isLiteralBit(bytelit)) != 0)
7785             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7786           else{
7787             if(bytelit != 0x0FFL)
7788               pic16_emitcode("anl","a,%s",
7789                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7790             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7791           }
7792 #endif
7793         }
7794         offset++;
7795       }
7796       // bit = left & literal
7797       if(size) {
7798         emitCLRC;
7799         pic16_emitpLabel(tlbl->key);
7800       }
7801       // if(left & literal)
7802       else {
7803         if(ifx) {
7804           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7805           ifx->generated = 1;
7806         }
7807         pic16_emitpLabel(tlbl->key);
7808         goto release;
7809       }
7810     }
7811
7812     pic16_outBitC(result);
7813     goto release ;
7814   }
7815
7816   /* if left is same as result */
7817   if(pic16_sameRegs(AOP(result),AOP(left))){
7818     int know_W = -1;
7819     for(;size--; offset++,lit>>=8) {
7820       if(AOP_TYPE(right) == AOP_LIT){
7821         switch(lit & 0xff) {
7822         case 0x00:
7823           /*  and'ing with 0 has clears the result */
7824 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7825           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7826           break;
7827         case 0xff:
7828           /* and'ing with 0xff is a nop when the result and left are the same */
7829           break;
7830
7831         default:
7832           {
7833             int p = pic16_my_powof2( (~lit) & 0xff );
7834             if(p>=0) {
7835               /* only one bit is set in the literal, so use a bcf instruction */
7836 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7837               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7838
7839             } else {
7840               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7841               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7842               if(know_W != (lit&0xff))
7843                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7844               know_W = lit &0xff;
7845               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7846             }
7847           }    
7848         }
7849       } else {
7850         if (AOP_TYPE(left) == AOP_ACC) {
7851           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7852         } else {                    
7853           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7854           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7855
7856         }
7857       }
7858     }
7859
7860   } else {
7861     // left & result in different registers
7862     if(AOP_TYPE(result) == AOP_CRY){
7863       // result = bit
7864       // if(size), result in bit
7865       // if(!size && ifx), conditional oper: if(left & right)
7866       symbol *tlbl = newiTempLabel(NULL);
7867       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7868       if(size)
7869         pic16_emitcode("setb","c");
7870       while(sizer--){
7871         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7872         pic16_emitcode("anl","a,%s",
7873                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7874         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7875         offset++;
7876       }
7877       if(size){
7878         CLRC;
7879         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7880         pic16_outBitC(result);
7881       } else if(ifx)
7882         jmpTrueOrFalse(ifx, tlbl);
7883     } else {
7884       for(;(size--);offset++) {
7885         // normal case
7886         // result = left & right
7887         if(AOP_TYPE(right) == AOP_LIT){
7888           int t = (lit >> (offset*8)) & 0x0FFL;
7889           switch(t) { 
7890           case 0x00:
7891             pic16_emitcode("clrf","%s",
7892                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7893             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7894             break;
7895           case 0xff:
7896             pic16_emitcode("movf","%s,w",
7897                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898             pic16_emitcode("movwf","%s",
7899                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7900             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7901             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7902             break;
7903           default:
7904             pic16_emitcode("movlw","0x%x",t);
7905             pic16_emitcode("andwf","%s,w",
7906                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907             pic16_emitcode("movwf","%s",
7908                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7909               
7910             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7911             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7912             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7913           }
7914           continue;
7915         }
7916
7917         if (AOP_TYPE(left) == AOP_ACC) {
7918           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7920         } else {
7921           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922           pic16_emitcode("andwf","%s,w",
7923                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7925           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7926         }
7927         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7928         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7929       }
7930     }
7931   }
7932
7933   release :
7934     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7935   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7936   pic16_freeAsmop(result,NULL,ic,TRUE);     
7937 }
7938
7939 /*-----------------------------------------------------------------*/
7940 /* genOr  - code for or                                            */
7941 /*-----------------------------------------------------------------*/
7942 static void genOr (iCode *ic, iCode *ifx)
7943 {
7944     operand *left, *right, *result;
7945     int size, offset=0;
7946     unsigned long lit = 0L;
7947
7948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7949
7950     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7951     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7952     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7953
7954     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7955
7956     /* if left is a literal & right is not then exchange them */
7957     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7958         AOP_NEEDSACC(left)) {
7959         operand *tmp = right ;
7960         right = left;
7961         left = tmp;
7962     }
7963
7964     /* if result = right then exchange them */
7965     if(pic16_sameRegs(AOP(result),AOP(right))){
7966         operand *tmp = right ;
7967         right = left;
7968         left = tmp;
7969     }
7970
7971     /* if right is bit then exchange them */
7972     if (AOP_TYPE(right) == AOP_CRY &&
7973         AOP_TYPE(left) != AOP_CRY){
7974         operand *tmp = right ;
7975         right = left;
7976         left = tmp;
7977     }
7978
7979     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7980
7981     if(AOP_TYPE(right) == AOP_LIT)
7982         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7983
7984     size = AOP_SIZE(result);
7985
7986     // if(bit | yy)
7987     // xx = bit | yy;
7988     if (AOP_TYPE(left) == AOP_CRY){
7989         if(AOP_TYPE(right) == AOP_LIT){
7990             // c = bit & literal;
7991             if(lit){
7992                 // lit != 0 => result = 1
7993                 if(AOP_TYPE(result) == AOP_CRY){
7994                   if(size)
7995                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7996                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7997                   //     AOP(result)->aopu.aop_dir,
7998                   //     AOP(result)->aopu.aop_dir);
7999                     else if(ifx)
8000                         continueIfTrue(ifx);
8001                     goto release;
8002                 }
8003             } else {
8004                 // lit == 0 => result = left
8005                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8006                     goto release;
8007                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8008             }
8009         } else {
8010             if (AOP_TYPE(right) == AOP_CRY){
8011               if(pic16_sameRegs(AOP(result),AOP(left))){
8012                 // c = bit | bit;
8013                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8014                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8015                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8016
8017                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8018                          AOP(result)->aopu.aop_dir,
8019                          AOP(result)->aopu.aop_dir);
8020                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8021                          AOP(right)->aopu.aop_dir,
8022                          AOP(right)->aopu.aop_dir);
8023                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8024                          AOP(result)->aopu.aop_dir,
8025                          AOP(result)->aopu.aop_dir);
8026               } else {
8027                 if( AOP_TYPE(result) == AOP_ACC) {
8028                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8029                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8030                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8031                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8032
8033                 } else {
8034
8035                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8036                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8037                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8038                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8039
8040                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8041                                  AOP(result)->aopu.aop_dir,
8042                                  AOP(result)->aopu.aop_dir);
8043                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8044                                  AOP(right)->aopu.aop_dir,
8045                                  AOP(right)->aopu.aop_dir);
8046                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8047                                  AOP(left)->aopu.aop_dir,
8048                                  AOP(left)->aopu.aop_dir);
8049                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8050                                  AOP(result)->aopu.aop_dir,
8051                                  AOP(result)->aopu.aop_dir);
8052                 }
8053               }
8054             } else {
8055                 // c = bit | val;
8056                 symbol *tlbl = newiTempLabel(NULL);
8057                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8058
8059
8060                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8061                 if( AOP_TYPE(right) == AOP_ACC) {
8062                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8063                   emitSKPNZ;
8064                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8065                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8066                 }
8067
8068
8069
8070                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8071                     pic16_emitcode(";XXX setb","c");
8072                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8073                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8074                 pic16_toBoolean(right);
8075                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8076                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8077                     jmpTrueOrFalse(ifx, tlbl);
8078                     goto release;
8079                 } else {
8080                     CLRC;
8081                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8082                 }
8083             }
8084         }
8085         // bit = c
8086         // val = c
8087         if(size)
8088             pic16_outBitC(result);
8089         // if(bit | ...)
8090         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8091             genIfxJump(ifx, "c");           
8092         goto release ;
8093     }
8094
8095     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8096     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8097     if((AOP_TYPE(right) == AOP_LIT) &&
8098        (AOP_TYPE(result) == AOP_CRY) &&
8099        (AOP_TYPE(left) != AOP_CRY)){
8100         if(lit){
8101           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8102             // result = 1
8103             if(size)
8104                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8105             else 
8106                 continueIfTrue(ifx);
8107             goto release;
8108         } else {
8109           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8110             // lit = 0, result = boolean(left)
8111             if(size)
8112                 pic16_emitcode(";XXX setb","c");
8113             pic16_toBoolean(right);
8114             if(size){
8115                 symbol *tlbl = newiTempLabel(NULL);
8116                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8117                 CLRC;
8118                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8119             } else {
8120                 genIfxJump (ifx,"a");
8121                 goto release;
8122             }
8123         }
8124         pic16_outBitC(result);
8125         goto release ;
8126     }
8127
8128     /* if left is same as result */
8129     if(pic16_sameRegs(AOP(result),AOP(left))){
8130       int know_W = -1;
8131       for(;size--; offset++,lit>>=8) {
8132         if(AOP_TYPE(right) == AOP_LIT){
8133           if((lit & 0xff) == 0)
8134             /*  or'ing with 0 has no effect */
8135             continue;
8136           else {
8137             int p = pic16_my_powof2(lit & 0xff);
8138             if(p>=0) {
8139               /* only one bit is set in the literal, so use a bsf instruction */
8140               pic16_emitpcode(POC_BSF,
8141                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8142             } else {
8143               if(know_W != (lit & 0xff))
8144                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8145               know_W = lit & 0xff;
8146               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8147             }
8148                     
8149           }
8150         } else {
8151           if (AOP_TYPE(left) == AOP_ACC) {
8152             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8153             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154           } else {                  
8155             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8156             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8157
8158             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8159             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8160
8161           }
8162         }
8163       }
8164     } else {
8165         // left & result in different registers
8166         if(AOP_TYPE(result) == AOP_CRY){
8167             // result = bit
8168             // if(size), result in bit
8169             // if(!size && ifx), conditional oper: if(left | right)
8170             symbol *tlbl = newiTempLabel(NULL);
8171             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8172             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8173
8174
8175             if(size)
8176                 pic16_emitcode(";XXX setb","c");
8177             while(sizer--){
8178                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8179                 pic16_emitcode(";XXX orl","a,%s",
8180                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8182                 offset++;
8183             }
8184             if(size){
8185                 CLRC;
8186                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8187                 pic16_outBitC(result);
8188             } else if(ifx)
8189                 jmpTrueOrFalse(ifx, tlbl);
8190         } else for(;(size--);offset++){
8191           // normal case
8192           // result = left & right
8193           if(AOP_TYPE(right) == AOP_LIT){
8194             int t = (lit >> (offset*8)) & 0x0FFL;
8195             switch(t) { 
8196             case 0x00:
8197               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8198               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8199
8200               pic16_emitcode("movf","%s,w",
8201                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202               pic16_emitcode("movwf","%s",
8203                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8204               break;
8205             default:
8206               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8207               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8208               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8209
8210               pic16_emitcode("movlw","0x%x",t);
8211               pic16_emitcode("iorwf","%s,w",
8212                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8213               pic16_emitcode("movwf","%s",
8214                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8215               
8216             }
8217             continue;
8218           }
8219
8220           // faster than result <- left, anl result,right
8221           // and better if result is SFR
8222           if (AOP_TYPE(left) == AOP_ACC) {
8223             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8224             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8225           } else {
8226             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8227             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8228
8229             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8230             pic16_emitcode("iorwf","%s,w",
8231                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8232           }
8233           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8234           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8235         }
8236     }
8237
8238 release :
8239     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8240     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8241     pic16_freeAsmop(result,NULL,ic,TRUE);     
8242 }
8243
8244 /*-----------------------------------------------------------------*/
8245 /* genXor - code for xclusive or                                   */
8246 /*-----------------------------------------------------------------*/
8247 static void genXor (iCode *ic, iCode *ifx)
8248 {
8249   operand *left, *right, *result;
8250   int size, offset=0;
8251   unsigned long lit = 0L;
8252
8253   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8254
8255   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8256   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8257   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8258
8259   /* if left is a literal & right is not ||
8260      if left needs acc & right does not */
8261   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8262       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8263     operand *tmp = right ;
8264     right = left;
8265     left = tmp;
8266   }
8267
8268   /* if result = right then exchange them */
8269   if(pic16_sameRegs(AOP(result),AOP(right))){
8270     operand *tmp = right ;
8271     right = left;
8272     left = tmp;
8273   }
8274
8275   /* if right is bit then exchange them */
8276   if (AOP_TYPE(right) == AOP_CRY &&
8277       AOP_TYPE(left) != AOP_CRY){
8278     operand *tmp = right ;
8279     right = left;
8280     left = tmp;
8281   }
8282   if(AOP_TYPE(right) == AOP_LIT)
8283     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8284
8285   size = AOP_SIZE(result);
8286
8287   // if(bit ^ yy)
8288   // xx = bit ^ yy;
8289   if (AOP_TYPE(left) == AOP_CRY){
8290     if(AOP_TYPE(right) == AOP_LIT){
8291       // c = bit & literal;
8292       if(lit>>1){
8293         // lit>>1  != 0 => result = 1
8294         if(AOP_TYPE(result) == AOP_CRY){
8295           if(size)
8296             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8297             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8298           else if(ifx)
8299             continueIfTrue(ifx);
8300           goto release;
8301         }
8302         pic16_emitcode("setb","c");
8303       } else{
8304         // lit == (0 or 1)
8305         if(lit == 0){
8306           // lit == 0, result = left
8307           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8308             goto release;
8309           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8310         } else{
8311           // lit == 1, result = not(left)
8312           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8313             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8314             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8315             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8316             goto release;
8317           } else {
8318             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8319             pic16_emitcode("cpl","c");
8320           }
8321         }
8322       }
8323
8324     } else {
8325       // right != literal
8326       symbol *tlbl = newiTempLabel(NULL);
8327       if (AOP_TYPE(right) == AOP_CRY){
8328         // c = bit ^ bit;
8329         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8330       }
8331       else{
8332         int sizer = AOP_SIZE(right);
8333         // c = bit ^ val
8334         // if val>>1 != 0, result = 1
8335         pic16_emitcode("setb","c");
8336         while(sizer){
8337           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8338           if(sizer == 1)
8339             // test the msb of the lsb
8340             pic16_emitcode("anl","a,#0xfe");
8341           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8342           sizer--;
8343         }
8344         // val = (0,1)
8345         pic16_emitcode("rrc","a");
8346       }
8347       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8348       pic16_emitcode("cpl","c");
8349       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8350     }
8351     // bit = c
8352     // val = c
8353     if(size)
8354       pic16_outBitC(result);
8355     // if(bit | ...)
8356     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8357       genIfxJump(ifx, "c");           
8358     goto release ;
8359   }
8360
8361   if(pic16_sameRegs(AOP(result),AOP(left))){
8362     /* if left is same as result */
8363     for(;size--; offset++) {
8364       if(AOP_TYPE(right) == AOP_LIT){
8365         int t  = (lit >> (offset*8)) & 0x0FFL;
8366         if(t == 0x00L)
8367           continue;
8368         else
8369           if (IS_AOP_PREG(left)) {
8370             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8372             pic16_aopPut(AOP(result),"a",offset);
8373           } else {
8374             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8375             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8376             pic16_emitcode("xrl","%s,%s",
8377                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8378                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8379           }
8380       } else {
8381         if (AOP_TYPE(left) == AOP_ACC)
8382           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8383         else {
8384           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8385           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8386 /*
8387           if (IS_AOP_PREG(left)) {
8388             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8389             pic16_aopPut(AOP(result),"a",offset);
8390           } else
8391             pic16_emitcode("xrl","%s,a",
8392                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8393 */
8394         }
8395       }
8396     }
8397   } else {
8398     // left & result in different registers
8399     if(AOP_TYPE(result) == AOP_CRY){
8400       // result = bit
8401       // if(size), result in bit
8402       // if(!size && ifx), conditional oper: if(left ^ right)
8403       symbol *tlbl = newiTempLabel(NULL);
8404       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8405       if(size)
8406         pic16_emitcode("setb","c");
8407       while(sizer--){
8408         if((AOP_TYPE(right) == AOP_LIT) &&
8409            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8410           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8411         } else {
8412           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8413           pic16_emitcode("xrl","a,%s",
8414                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8415         }
8416         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8417         offset++;
8418       }
8419       if(size){
8420         CLRC;
8421         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8422         pic16_outBitC(result);
8423       } else if(ifx)
8424         jmpTrueOrFalse(ifx, tlbl);
8425     } else for(;(size--);offset++){
8426       // normal case
8427       // result = left & right
8428       if(AOP_TYPE(right) == AOP_LIT){
8429         int t = (lit >> (offset*8)) & 0x0FFL;
8430         switch(t) { 
8431         case 0x00:
8432           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8433           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8434           pic16_emitcode("movf","%s,w",
8435                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8436           pic16_emitcode("movwf","%s",
8437                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8438           break;
8439         case 0xff:
8440           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8441           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8442           pic16_emitcode("comf","%s,w",
8443                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8444           pic16_emitcode("movwf","%s",
8445                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8446           break;
8447         default:
8448           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8449           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8450           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8451           pic16_emitcode("movlw","0x%x",t);
8452           pic16_emitcode("xorwf","%s,w",
8453                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8454           pic16_emitcode("movwf","%s",
8455                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8456
8457         }
8458         continue;
8459       }
8460
8461       // faster than result <- left, anl result,right
8462       // and better if result is SFR
8463       if (AOP_TYPE(left) == AOP_ACC) {
8464         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8465         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8466       } else {
8467         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8468         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8469         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8470         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8471       }
8472       if ( AOP_TYPE(result) != AOP_ACC){
8473         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8474         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8475       }
8476     }
8477   }
8478
8479   release :
8480     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8481   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8482   pic16_freeAsmop(result,NULL,ic,TRUE);     
8483 }
8484
8485 /*-----------------------------------------------------------------*/
8486 /* genInline - write the inline code out                           */
8487 /*-----------------------------------------------------------------*/
8488 static void genInline (iCode *ic)
8489 {
8490   char *buffer, *bp, *bp1;
8491     
8492         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8493
8494         _G.inLine += (!options.asmpeep);
8495
8496         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8497         strcpy(buffer,IC_INLINE(ic));
8498
8499 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8500
8501         /* emit each line as a code */
8502         while (*bp) {
8503                 if (*bp == '\n') {
8504                         *bp++ = '\0';
8505
8506                         if(*bp1)
8507                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8508                         bp1 = bp;
8509                 } else {
8510                         if (*bp == ':') {
8511                                 bp++;
8512                                 *bp = '\0';
8513                                 bp++;
8514
8515                                 /* print label, use this special format with NULL directive
8516                                  * to denote that the argument should not be indented with tab */
8517                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8518                                 bp1 = bp;
8519                         } else
8520                                 bp++;
8521                 }
8522         }
8523
8524         if ((bp1 != bp) && *bp1)
8525                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8526
8527
8528     Safe_free(buffer);
8529
8530     _G.inLine -= (!options.asmpeep);
8531 }
8532
8533 /*-----------------------------------------------------------------*/
8534 /* genRRC - rotate right with carry                                */
8535 /*-----------------------------------------------------------------*/
8536 static void genRRC (iCode *ic)
8537 {
8538   operand *left , *result ;
8539   int size, offset = 0, same;
8540
8541   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8542
8543   /* rotate right with carry */
8544   left = IC_LEFT(ic);
8545   result=IC_RESULT(ic);
8546   pic16_aopOp (left,ic,FALSE);
8547   pic16_aopOp (result,ic,FALSE);
8548
8549   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8550
8551   same = pic16_sameRegs(AOP(result),AOP(left));
8552
8553   size = AOP_SIZE(result);    
8554
8555   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8556
8557   /* get the lsb and put it into the carry */
8558   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8559
8560   offset = 0 ;
8561
8562   while(size--) {
8563
8564     if(same) {
8565       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8566     } else {
8567       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8568       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8569     }
8570
8571     offset++;
8572   }
8573
8574   pic16_freeAsmop(left,NULL,ic,TRUE);
8575   pic16_freeAsmop(result,NULL,ic,TRUE);
8576 }
8577
8578 /*-----------------------------------------------------------------*/
8579 /* genRLC - generate code for rotate left with carry               */
8580 /*-----------------------------------------------------------------*/
8581 static void genRLC (iCode *ic)
8582 {    
8583   operand *left , *result ;
8584   int size, offset = 0;
8585   int same;
8586
8587   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8588   /* rotate right with carry */
8589   left = IC_LEFT(ic);
8590   result=IC_RESULT(ic);
8591   pic16_aopOp (left,ic,FALSE);
8592   pic16_aopOp (result,ic,FALSE);
8593
8594   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8595
8596   same = pic16_sameRegs(AOP(result),AOP(left));
8597
8598   /* move it to the result */
8599   size = AOP_SIZE(result);    
8600
8601   /* get the msb and put it into the carry */
8602   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8603
8604   offset = 0 ;
8605
8606   while(size--) {
8607
8608     if(same) {
8609       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8610     } else {
8611       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8612       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8613     }
8614
8615     offset++;
8616   }
8617
8618
8619   pic16_freeAsmop(left,NULL,ic,TRUE);
8620   pic16_freeAsmop(result,NULL,ic,TRUE);
8621 }
8622
8623
8624 /* gpasm can get the highest order bit with HIGH/UPPER
8625  * so the following probably is not needed -- VR */
8626  
8627 /*-----------------------------------------------------------------*/
8628 /* genGetHbit - generates code get highest order bit               */
8629 /*-----------------------------------------------------------------*/
8630 static void genGetHbit (iCode *ic)
8631 {
8632     operand *left, *result;
8633     left = IC_LEFT(ic);
8634     result=IC_RESULT(ic);
8635     pic16_aopOp (left,ic,FALSE);
8636     pic16_aopOp (result,ic,FALSE);
8637
8638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8639     /* get the highest order byte into a */
8640     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8641     if(AOP_TYPE(result) == AOP_CRY){
8642         pic16_emitcode("rlc","a");
8643         pic16_outBitC(result);
8644     }
8645     else{
8646         pic16_emitcode("rl","a");
8647         pic16_emitcode("anl","a,#0x01");
8648         pic16_outAcc(result);
8649     }
8650
8651
8652     pic16_freeAsmop(left,NULL,ic,TRUE);
8653     pic16_freeAsmop(result,NULL,ic,TRUE);
8654 }
8655
8656 #if 0
8657 /*-----------------------------------------------------------------*/
8658 /* AccRol - rotate left accumulator by known count                 */
8659 /*-----------------------------------------------------------------*/
8660 static void AccRol (int shCount)
8661 {
8662     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8663     shCount &= 0x0007;              // shCount : 0..7
8664     switch(shCount){
8665         case 0 :
8666             break;
8667         case 1 :
8668             pic16_emitcode("rl","a");
8669             break;
8670         case 2 :
8671             pic16_emitcode("rl","a");
8672             pic16_emitcode("rl","a");
8673             break;
8674         case 3 :
8675             pic16_emitcode("swap","a");
8676             pic16_emitcode("rr","a");
8677             break;
8678         case 4 :
8679             pic16_emitcode("swap","a");
8680             break;
8681         case 5 :
8682             pic16_emitcode("swap","a");
8683             pic16_emitcode("rl","a");
8684             break;
8685         case 6 :
8686             pic16_emitcode("rr","a");
8687             pic16_emitcode("rr","a");
8688             break;
8689         case 7 :
8690             pic16_emitcode("rr","a");
8691             break;
8692     }
8693 }
8694 #endif
8695
8696 /*-----------------------------------------------------------------*/
8697 /* AccLsh - left shift accumulator by known count                  */
8698 /*-----------------------------------------------------------------*/
8699 static void AccLsh (int shCount)
8700 {
8701         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8702         switch(shCount){
8703                 case 0 :
8704                         return;
8705                         break;
8706                 case 1 :
8707                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8708                         break;
8709                 case 2 :
8710                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8711                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8712                         break;
8713                 case 3 :
8714                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8715                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8716                         break;
8717                 case 4 :
8718                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8719                         break;
8720                 case 5 :
8721                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8722                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8723                         break;
8724                 case 6 :
8725                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8726                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8727                         break;
8728                 case 7 :
8729                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8730                         break;
8731         }
8732
8733         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8734 }
8735
8736 /*-----------------------------------------------------------------*/
8737 /* AccRsh - right shift accumulator by known count                 */
8738 /*-----------------------------------------------------------------*/
8739 static void AccRsh (int shCount, int andmask)
8740 {
8741         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8742         switch(shCount){
8743                 case 0 :
8744                         return; break;
8745                 case 1 :
8746                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8747                         break;
8748                 case 2 :
8749                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8750                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8751                         break;
8752                 case 3 :
8753                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8754                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8755                         break;
8756                 case 4 :
8757                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8758                         break;
8759                 case 5 :
8760                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8761                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8762                         break;
8763                 case 6 :
8764                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8766                         break;
8767                 case 7 :
8768                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769                         break;
8770         }
8771         
8772         if(andmask)
8773                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8774         else
8775                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8776 }
8777
8778 #if 0
8779 /*-----------------------------------------------------------------*/
8780 /* AccSRsh - signed right shift accumulator by known count                 */
8781 /*-----------------------------------------------------------------*/
8782 static void AccSRsh (int shCount)
8783 {
8784     symbol *tlbl ;
8785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8786     if(shCount != 0){
8787         if(shCount == 1){
8788             pic16_emitcode("mov","c,acc.7");
8789             pic16_emitcode("rrc","a");
8790         } else if(shCount == 2){
8791             pic16_emitcode("mov","c,acc.7");
8792             pic16_emitcode("rrc","a");
8793             pic16_emitcode("mov","c,acc.7");
8794             pic16_emitcode("rrc","a");
8795         } else {
8796             tlbl = newiTempLabel(NULL);
8797             /* rotate right accumulator */
8798             AccRol(8 - shCount);
8799             /* and kill the higher order bits */
8800             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8801             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8802             pic16_emitcode("orl","a,#0x%02x",
8803                      (unsigned char)~SRMask[shCount]);
8804             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8805         }
8806     }
8807 }
8808 #endif
8809
8810 /*-----------------------------------------------------------------*/
8811 /* shiftR1Left2Result - shift right one byte from left to result   */
8812 /*-----------------------------------------------------------------*/
8813 static void shiftR1Left2ResultSigned (operand *left, int offl,
8814                                 operand *result, int offr,
8815                                 int shCount)
8816 {
8817   int same;
8818
8819   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8820
8821   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8822
8823   switch(shCount) {
8824   case 1:
8825     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8826     if(same) 
8827       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8828     else {
8829       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8830       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8831     }
8832
8833     break;
8834   case 2:
8835
8836     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8837     if(same) 
8838       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8839     else {
8840       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8841       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8842     }
8843     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8844     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8845
8846     break;
8847
8848   case 3:
8849     if(same)
8850       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8851     else {
8852       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8853       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8854     }
8855
8856     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8857     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8859
8860     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8861     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8862
8863     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8864     break;
8865
8866   case 4:
8867     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8868     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8869     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8870     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8871     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8872     break;
8873   case 5:
8874     if(same) {
8875       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8876     } else {
8877       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8878       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8879     }
8880     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8881     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8882     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8883     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8884     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8885     break;
8886
8887   case 6:
8888     if(same) {
8889       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8890       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8891       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8892       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8893       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8894       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8895     } else {
8896       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8897       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8898       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8899       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8900       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8901     }
8902     break;
8903
8904   case 7:
8905     if(same) {
8906       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8907       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8908       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8909       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910     } else {
8911       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8912       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8913       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8914     }
8915
8916   default:
8917     break;
8918   }
8919 }
8920
8921 /*-----------------------------------------------------------------*/
8922 /* shiftR1Left2Result - shift right one byte from left to result   */
8923 /*-----------------------------------------------------------------*/
8924 static void shiftR1Left2Result (operand *left, int offl,
8925                                 operand *result, int offr,
8926                                 int shCount, int sign)
8927 {
8928   int same;
8929
8930   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8931
8932   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8933
8934   /* Copy the msb into the carry if signed. */
8935   if(sign) {
8936     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8937     return;
8938   }
8939
8940
8941
8942   switch(shCount) {
8943   case 1:
8944     emitCLRC;
8945     if(same) 
8946       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8947     else {
8948       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8949       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8950     }
8951     break;
8952   case 2:
8953     emitCLRC;
8954     if(same) {
8955       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8956     } else {
8957       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8958       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8959     }
8960     emitCLRC;
8961     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8962
8963     break;
8964   case 3:
8965     if(same)
8966       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8967     else {
8968       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8969       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8970     }
8971
8972     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8973     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8974     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8975     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8976     break;
8977       
8978   case 4:
8979     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8980     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8981     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8982     break;
8983
8984   case 5:
8985     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8986     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8987     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988     //emitCLRC;
8989     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8990
8991     break;
8992   case 6:
8993
8994     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8995     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8996     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8997     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8998     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8999     break;
9000
9001   case 7:
9002
9003     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9004     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9005     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9006
9007     break;
9008
9009   default:
9010     break;
9011   }
9012 }
9013
9014 /*-----------------------------------------------------------------*/
9015 /* shiftL1Left2Result - shift left one byte from left to result    */
9016 /*-----------------------------------------------------------------*/
9017 static void shiftL1Left2Result (operand *left, int offl,
9018                                 operand *result, int offr, int shCount)
9019 {
9020   int same;
9021
9022   //    char *l;
9023   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9024
9025   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9026   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9027     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9028     //    MOVA(l);
9029     /* shift left accumulator */
9030     //AccLsh(shCount); // don't comment out just yet...
9031   //    pic16_aopPut(AOP(result),"a",offr);
9032
9033   switch(shCount) {
9034   case 1:
9035     /* Shift left 1 bit position */
9036     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9037     if(same) {
9038       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9039     } else {
9040       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9041       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9042     }
9043     break;
9044   case 2:
9045     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9046     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9047     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9048     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9049     break;
9050   case 3:
9051     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9052     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9053     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9054     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9055     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9056     break;
9057   case 4:
9058     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9059     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9060     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9061     break;
9062   case 5:
9063     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9064     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9065     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9066     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9067     break;
9068   case 6:
9069     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9070     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9071     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9072     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9073     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9074     break;
9075   case 7:
9076     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9077     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9078     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9079     break;
9080
9081   default:
9082     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9083   }
9084
9085 }
9086
9087 /*-----------------------------------------------------------------*/
9088 /* movLeft2Result - move byte from left to result                  */
9089 /*-----------------------------------------------------------------*/
9090 static void movLeft2Result (operand *left, int offl,
9091                             operand *result, int offr)
9092 {
9093   char *l;
9094   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9095   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9096     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9097
9098     if (*l == '@' && (IS_AOP_PREG(result))) {
9099       pic16_emitcode("mov","a,%s",l);
9100       pic16_aopPut(AOP(result),"a",offr);
9101     } else {
9102       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9103       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9104     }
9105   }
9106 }
9107
9108 /*-----------------------------------------------------------------*/
9109 /* shiftL2Left2Result - shift left two bytes from left to result   */
9110 /*-----------------------------------------------------------------*/
9111 static void shiftL2Left2Result (operand *left, int offl,
9112                                 operand *result, int offr, int shCount)
9113 {
9114   int same = pic16_sameRegs(AOP(result), AOP(left));
9115   int i;
9116
9117   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9118
9119   if (same && (offl != offr)) { // shift bytes
9120     if (offr > offl) {
9121        for(i=1;i>-1;i--) {
9122          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9123          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9124        }
9125     } else { // just treat as different later on
9126                 same = 0;
9127     }
9128   }
9129
9130   if(same) {
9131     switch(shCount) {
9132     case 0:
9133       break;
9134     case 1:
9135     case 2:
9136     case 3:
9137
9138       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9139       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9140       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9141
9142       while(--shCount) {
9143                 emitCLRC;
9144                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9145                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9146       }
9147
9148       break;
9149     case 4:
9150     case 5:
9151       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9152       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9154       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9155       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9156       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9158       if(shCount >=5) {
9159                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9160                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9161       }
9162       break;
9163     case 6:
9164       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9166       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9167       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9168       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9169       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9170       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9171       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9172       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9173       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9174       break;
9175     case 7:
9176       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9177       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9178       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9179       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9180       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9181     }
9182
9183   } else {
9184     switch(shCount) {
9185     case 0:
9186       break;
9187     case 1:
9188     case 2:
9189     case 3:
9190       /* note, use a mov/add for the shift since the mov has a
9191          chance of getting optimized out */
9192       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9193       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9194       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9195       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9196       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9197
9198       while(--shCount) {
9199                 emitCLRC;
9200                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9201                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9202       }
9203       break;
9204
9205     case 4:
9206     case 5:
9207       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9208       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9209       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9210       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9211       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9212       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9213       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9214       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9215
9216
9217       if(shCount == 5) {
9218                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9219                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9220       }
9221       break;
9222     case 6:
9223       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9224       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9225       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9226       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9227
9228       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9229       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9230       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9231       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9232       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9235       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9236       break;
9237     case 7:
9238       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9239       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9240       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9242       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9243     }
9244   }
9245
9246 }
9247 /*-----------------------------------------------------------------*/
9248 /* shiftR2Left2Result - shift right two bytes from left to result  */
9249 /*-----------------------------------------------------------------*/
9250 static void shiftR2Left2Result (operand *left, int offl,
9251                                 operand *result, int offr,
9252                                 int shCount, int sign)
9253 {
9254   int same = pic16_sameRegs(AOP(result), AOP(left));
9255   int i;
9256   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9257
9258   if (same && (offl != offr)) { // shift right bytes
9259     if (offr < offl) {
9260        for(i=0;i<2;i++) {
9261          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9262          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9263        }
9264     } else { // just treat as different later on
9265                 same = 0;
9266     }
9267   }
9268
9269   switch(shCount) {
9270   case 0:
9271     break;
9272   case 1:
9273   case 2:
9274   case 3:
9275     if(sign)
9276       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9277     else
9278       emitCLRC;
9279
9280     if(same) {
9281       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9282       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9283     } else {
9284       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9285       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9286       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9287       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9288     }
9289
9290     while(--shCount) {
9291       if(sign)
9292                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9293       else
9294                 emitCLRC;
9295       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9296       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9297     }
9298     break;
9299   case 4:
9300   case 5:
9301     if(same) {
9302
9303       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9304       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9305       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9306
9307       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9308       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9309       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9310       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9311     } else {
9312       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9313       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9314       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9315
9316       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9317       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9318       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9319       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9320       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9321     }
9322
9323     if(shCount >=5) {
9324       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9325       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9326     }
9327
9328     if(sign) {
9329       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9330       pic16_emitpcode(POC_BTFSC, 
9331                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9332       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9333     }
9334
9335     break;
9336
9337   case 6:
9338     if(same) {
9339
9340       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9341       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9342
9343       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9344       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9345       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9346       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9347       if(sign) {
9348         pic16_emitpcode(POC_BTFSC, 
9349                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9350         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9351       }
9352       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9353       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9354       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9355       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9356     } else {
9357       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9358       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9359       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9360       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9361       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9362       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9363       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9364       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9365       if(sign) {
9366         pic16_emitpcode(POC_BTFSC, 
9367                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9368         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9369       }
9370       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9372
9373         
9374     }
9375
9376     break;
9377   case 7:
9378     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9379     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9380     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9381     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9382     if(sign) {
9383       emitSKPNC;
9384       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9385     } else 
9386       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9387   }
9388 }
9389
9390
9391 /*-----------------------------------------------------------------*/
9392 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9393 /*-----------------------------------------------------------------*/
9394 static void shiftLLeftOrResult (operand *left, int offl,
9395                                 operand *result, int offr, int shCount)
9396 {
9397     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9398
9399     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9400     /* shift left accumulator */
9401     AccLsh(shCount);
9402     /* or with result */
9403     /* back to result */
9404     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9405 }
9406
9407 /*-----------------------------------------------------------------*/
9408 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9409 /*-----------------------------------------------------------------*/
9410 static void shiftRLeftOrResult (operand *left, int offl,
9411                                 operand *result, int offr, int shCount)
9412 {
9413     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9414     
9415     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9416     /* shift right accumulator */
9417     AccRsh(shCount, 1);
9418     /* or with result */
9419     /* back to result */
9420     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9421 }
9422
9423 /*-----------------------------------------------------------------*/
9424 /* genlshOne - left shift a one byte quantity by known count       */
9425 /*-----------------------------------------------------------------*/
9426 static void genlshOne (operand *result, operand *left, int shCount)
9427 {       
9428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9429     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9430 }
9431
9432 /*-----------------------------------------------------------------*/
9433 /* genlshTwo - left shift two bytes by known amount != 0           */
9434 /*-----------------------------------------------------------------*/
9435 static void genlshTwo (operand *result,operand *left, int shCount)
9436 {
9437     int size;
9438     
9439     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9440     size = pic16_getDataSize(result);
9441
9442     /* if shCount >= 8 */
9443     if (shCount >= 8) {
9444         shCount -= 8 ;
9445
9446         if (size > 1){
9447             if (shCount)
9448                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9449             else 
9450                 movLeft2Result(left, LSB, result, MSB16);
9451         }
9452         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9453     }
9454
9455     /*  1 <= shCount <= 7 */
9456     else {  
9457         if(size == 1)
9458             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9459         else 
9460             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9461     }
9462 }
9463
9464 /*-----------------------------------------------------------------*/
9465 /* shiftLLong - shift left one long from left to result            */
9466 /* offr = LSB or MSB16                                             */
9467 /*-----------------------------------------------------------------*/
9468 static void shiftLLong (operand *left, operand *result, int offr )
9469 {
9470     int size = AOP_SIZE(result);
9471     int same = pic16_sameRegs(AOP(left),AOP(result));
9472         int i;
9473
9474     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9475
9476         if (same && (offr == MSB16)) { //shift one byte
9477                 for(i=size-1;i>=MSB16;i--) {
9478                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9479                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9480                 }
9481         } else {
9482                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9483         }
9484         
9485     if (size > LSB+offr ){
9486                 if (same) {
9487                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9488                 } else {
9489                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9490                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9491                 }
9492          }
9493
9494     if(size > MSB16+offr){
9495                 if (same) {
9496                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9497                 } else {
9498                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9499                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9500                 }
9501     }
9502
9503     if(size > MSB24+offr){
9504                 if (same) {
9505                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9506                 } else {
9507                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9508                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9509                 }
9510     }
9511
9512     if(size > MSB32+offr){
9513                 if (same) {
9514                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9515                 } else {
9516                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9517                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9518                 }
9519     }
9520     if(offr != LSB)
9521                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9522
9523 }
9524
9525 /*-----------------------------------------------------------------*/
9526 /* genlshFour - shift four byte by a known amount != 0             */
9527 /*-----------------------------------------------------------------*/
9528 static void genlshFour (operand *result, operand *left, int shCount)
9529 {
9530     int size;
9531
9532     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533     size = AOP_SIZE(result);
9534
9535     /* if shifting more that 3 bytes */
9536     if (shCount >= 24 ) {
9537         shCount -= 24;
9538         if (shCount)
9539             /* lowest order of left goes to the highest
9540             order of the destination */
9541             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9542         else
9543             movLeft2Result(left, LSB, result, MSB32);
9544
9545                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9546                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9547                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9548
9549         return;
9550     }
9551
9552     /* more than two bytes */
9553     else if ( shCount >= 16 ) {
9554         /* lower order two bytes goes to higher order two bytes */
9555         shCount -= 16;
9556         /* if some more remaining */
9557         if (shCount)
9558             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9559         else {
9560             movLeft2Result(left, MSB16, result, MSB32);
9561             movLeft2Result(left, LSB, result, MSB24);
9562         }
9563                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9564                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9565         return;
9566     }    
9567
9568     /* if more than 1 byte */
9569     else if ( shCount >= 8 ) {
9570         /* lower order three bytes goes to higher order  three bytes */
9571         shCount -= 8;
9572         if(size == 2){
9573             if(shCount)
9574                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9575             else
9576                 movLeft2Result(left, LSB, result, MSB16);
9577         }
9578         else{   /* size = 4 */
9579             if(shCount == 0){
9580                 movLeft2Result(left, MSB24, result, MSB32);
9581                 movLeft2Result(left, MSB16, result, MSB24);
9582                 movLeft2Result(left, LSB, result, MSB16);
9583                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9584             }
9585             else if(shCount == 1)
9586                 shiftLLong(left, result, MSB16);
9587             else{
9588                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9589                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9590                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9591                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9592             }
9593         }
9594     }
9595
9596     /* 1 <= shCount <= 7 */
9597     else if(shCount <= 3)
9598     { 
9599         shiftLLong(left, result, LSB);
9600         while(--shCount >= 1)
9601             shiftLLong(result, result, LSB);
9602     }
9603     /* 3 <= shCount <= 7, optimize */
9604     else{
9605         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9606         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9607         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9608     }
9609 }
9610
9611 /*-----------------------------------------------------------------*/
9612 /* genLeftShiftLiteral - left shifting by known count              */
9613 /*-----------------------------------------------------------------*/
9614 void pic16_genLeftShiftLiteral (operand *left,
9615                                  operand *right,
9616                                  operand *result,
9617                                  iCode *ic)
9618 {    
9619     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9620     int size;
9621
9622     FENTRY;
9623     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9624     pic16_freeAsmop(right,NULL,ic,TRUE);
9625
9626     pic16_aopOp(left,ic,FALSE);
9627     pic16_aopOp(result,ic,FALSE);
9628
9629     size = getSize(operandType(result));
9630
9631 #if VIEW_SIZE
9632     pic16_emitcode("; shift left ","result %d, left %d",size,
9633              AOP_SIZE(left));
9634 #endif
9635
9636     /* I suppose that the left size >= result size */
9637     if(shCount == 0){
9638         while(size--){
9639             movLeft2Result(left, size, result, size);
9640         }
9641     }
9642
9643     else if(shCount >= (size * 8))
9644         while(size--)
9645             pic16_aopPut(AOP(result),zero,size);
9646     else{
9647         switch (size) {
9648             case 1:
9649                 genlshOne (result,left,shCount);
9650                 break;
9651
9652             case 2:
9653             case 3:
9654                 genlshTwo (result,left,shCount);
9655                 break;
9656
9657             case 4:
9658                 genlshFour (result,left,shCount);
9659                 break;
9660         }
9661     }
9662     pic16_freeAsmop(left,NULL,ic,TRUE);
9663     pic16_freeAsmop(result,NULL,ic,TRUE);
9664 }
9665
9666 /*-----------------------------------------------------------------*
9667  * genMultiAsm - repeat assembly instruction for size of register.
9668  * if endian == 1, then the high byte (i.e base address + size of 
9669  * register) is used first else the low byte is used first;
9670  *-----------------------------------------------------------------*/
9671 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9672 {
9673
9674   int offset = 0;
9675
9676   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9677
9678   if(!reg)
9679     return;
9680
9681   if(!endian) {
9682     endian = 1;
9683   } else {
9684     endian = -1;
9685     offset = size-1;
9686   }
9687
9688   while(size--) {
9689     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9690     offset += endian;
9691   }
9692
9693 }
9694
9695 #if !(USE_GENERIC_SIGNED_SHIFT)
9696 /*-----------------------------------------------------------------*/
9697 /* genLeftShift - generates code for left shifting                 */
9698 /*-----------------------------------------------------------------*/
9699 static void genLeftShift (iCode *ic)
9700 {
9701   operand *left,*right, *result;
9702   int size, offset;
9703 //  char *l;
9704   symbol *tlbl , *tlbl1;
9705   pCodeOp *pctemp;
9706
9707   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9708
9709   right = IC_RIGHT(ic);
9710   left  = IC_LEFT(ic);
9711   result = IC_RESULT(ic);
9712
9713   pic16_aopOp(right,ic,FALSE);
9714
9715   /* if the shift count is known then do it 
9716      as efficiently as possible */
9717   if (AOP_TYPE(right) == AOP_LIT) {
9718     pic16_genLeftShiftLiteral (left,right,result,ic);
9719     return ;
9720   }
9721
9722   /* shift count is unknown then we have to form
9723    * a loop. Get the loop count in WREG : Note: we take
9724    * only the lower order byte since shifting
9725    * more than 32 bits make no sense anyway, ( the
9726    * largest size of an object can be only 32 bits ) */
9727   
9728   pic16_aopOp(left,ic,FALSE);
9729   pic16_aopOp(result,ic,FALSE);
9730
9731   /* now move the left to the result if they are not the
9732    * same, and if size > 1,
9733    * and if right is not same to result (!!!) -- VR */
9734   if (!pic16_sameRegs(AOP(left),AOP(result))
9735       && (AOP_SIZE(result) > 1)) {
9736
9737     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9738
9739     size = AOP_SIZE(result);
9740     offset=0;
9741     while (size--) {
9742
9743 #if 0
9744       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9745       if (*l == '@' && (IS_AOP_PREG(result))) {
9746
9747           pic16_emitcode("mov","a,%s",l);
9748           pic16_aopPut(AOP(result),"a",offset);
9749       } else
9750 #endif
9751       {
9752         /* we don't know if left is a literal or a register, take care -- VR */
9753         mov2f(AOP(result), AOP(left), offset);
9754       }
9755       offset++;
9756     }
9757   }
9758
9759   size = AOP_SIZE(result);
9760
9761   /* if it is only one byte then */
9762   if (size == 1) {
9763     if(optimized_for_speed) {
9764       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9765       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9766       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9767       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9768       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9770       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9771       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9772       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9773       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9774       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9775       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9776     } else {
9777
9778       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9779
9780       tlbl = newiTempLabel(NULL);
9781
9782 #if 1
9783       /* this is already done, why change it? */
9784       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9785                 mov2f(AOP(result), AOP(left), 0);
9786       }
9787 #endif
9788
9789       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9790       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9791       pic16_emitpLabel(tlbl->key);
9792       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9793       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9794       emitSKPC;
9795       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796     }
9797     goto release ;
9798   }
9799     
9800   if (pic16_sameRegs(AOP(left),AOP(result))) {
9801
9802     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9803     
9804     tlbl = newiTempLabel(NULL);
9805     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9806     genMultiAsm(POC_RRCF, result, size,1);
9807     pic16_emitpLabel(tlbl->key);
9808     genMultiAsm(POC_RLCF, result, size,0);
9809     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9810     emitSKPC;
9811     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9812     goto release;
9813   }
9814
9815   //tlbl = newiTempLabel(NULL);
9816   //offset = 0 ;   
9817   //tlbl1 = newiTempLabel(NULL);
9818
9819   //reAdjustPreg(AOP(result));    
9820     
9821   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9822   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9823   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9824   //MOVA(l);
9825   //pic16_emitcode("add","a,acc");         
9826   //pic16_aopPut(AOP(result),"a",offset++);
9827   //while (--size) {
9828   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9829   //  MOVA(l);
9830   //  pic16_emitcode("rlc","a");         
9831   //  pic16_aopPut(AOP(result),"a",offset++);
9832   //}
9833   //reAdjustPreg(AOP(result));
9834
9835   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9836   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9837
9838
9839   tlbl = newiTempLabel(NULL);
9840   tlbl1= newiTempLabel(NULL);
9841
9842   size = AOP_SIZE(result);
9843   offset = 1;
9844
9845   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9846
9847   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9848
9849   /* offset should be 0, 1 or 3 */
9850   
9851   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9852   emitSKPNZ;
9853   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9854
9855   pic16_emitpcode(POC_MOVWF, pctemp);
9856
9857
9858   pic16_emitpLabel(tlbl->key);
9859
9860   emitCLRC;
9861   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9862   while(--size)
9863     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9864
9865   pic16_emitpcode(POC_DECFSZ,  pctemp);
9866   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9867   pic16_emitpLabel(tlbl1->key);
9868
9869   pic16_popReleaseTempReg(pctemp,1);
9870
9871
9872  release:
9873   pic16_freeAsmop (right,NULL,ic,TRUE);
9874   pic16_freeAsmop(left,NULL,ic,TRUE);
9875   pic16_freeAsmop(result,NULL,ic,TRUE);
9876 }
9877 #endif
9878
9879
9880 #if 0
9881 #error old code (left here for reference)
9882 /*-----------------------------------------------------------------*/
9883 /* genLeftShift - generates code for left shifting                 */
9884 /*-----------------------------------------------------------------*/
9885 static void genLeftShift (iCode *ic)
9886 {
9887   operand *left,*right, *result;
9888   int size, offset;
9889   char *l;
9890   symbol *tlbl , *tlbl1;
9891   pCodeOp *pctemp;
9892
9893   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9894
9895   right = IC_RIGHT(ic);
9896   left  = IC_LEFT(ic);
9897   result = IC_RESULT(ic);
9898
9899   pic16_aopOp(right,ic,FALSE);
9900
9901   /* if the shift count is known then do it 
9902      as efficiently as possible */
9903   if (AOP_TYPE(right) == AOP_LIT) {
9904     pic16_genLeftShiftLiteral (left,right,result,ic);
9905     return ;
9906   }
9907
9908   /* shift count is unknown then we have to form 
9909      a loop get the loop count in B : Note: we take
9910      only the lower order byte since shifting
9911      more that 32 bits make no sense anyway, ( the
9912      largest size of an object can be only 32 bits ) */  
9913
9914     
9915   pic16_aopOp(left,ic,FALSE);
9916   pic16_aopOp(result,ic,FALSE);
9917
9918   /* now move the left to the result if they are not the
9919      same */
9920   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9921       AOP_SIZE(result) > 1) {
9922
9923     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9924
9925     size = AOP_SIZE(result);
9926     offset=0;
9927     while (size--) {
9928       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9929       if (*l == '@' && (IS_AOP_PREG(result))) {
9930
9931         pic16_emitcode("mov","a,%s",l);
9932         pic16_aopPut(AOP(result),"a",offset);
9933       } else {
9934
9935         /* we don't know if left is a literal or a register, take care -- VR */
9936         mov2f(AOP(result), AOP(left), offset);
9937       }
9938       offset++;
9939     }
9940   }
9941
9942   size = AOP_SIZE(result);
9943
9944   /* if it is only one byte then */
9945   if (size == 1) {
9946     if(optimized_for_speed) {
9947       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9948       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9949       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9950       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9951       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9952       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9953       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9954       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9955       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9956       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9957       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9958       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9959     } else {
9960
9961       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9962
9963       tlbl = newiTempLabel(NULL);
9964       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9965                 mov2f(AOP(result), AOP(left), 0);
9966                 
9967 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9968 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9969       }
9970
9971       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9972       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9973       pic16_emitpLabel(tlbl->key);
9974       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9975       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9976       emitSKPC;
9977       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9978     }
9979     goto release ;
9980   }
9981     
9982   if (pic16_sameRegs(AOP(left),AOP(result))) {
9983
9984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9985     
9986     tlbl = newiTempLabel(NULL);
9987     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9988     genMultiAsm(POC_RRCF, result, size,1);
9989     pic16_emitpLabel(tlbl->key);
9990     genMultiAsm(POC_RLCF, result, size,0);
9991     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9992     emitSKPC;
9993     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9994     goto release;
9995   }
9996
9997   //tlbl = newiTempLabel(NULL);
9998   //offset = 0 ;   
9999   //tlbl1 = newiTempLabel(NULL);
10000
10001   //reAdjustPreg(AOP(result));    
10002     
10003   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10004   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10005   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10006   //MOVA(l);
10007   //pic16_emitcode("add","a,acc");         
10008   //pic16_aopPut(AOP(result),"a",offset++);
10009   //while (--size) {
10010   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10011   //  MOVA(l);
10012   //  pic16_emitcode("rlc","a");         
10013   //  pic16_aopPut(AOP(result),"a",offset++);
10014   //}
10015   //reAdjustPreg(AOP(result));
10016
10017   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10018   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10019
10020
10021   tlbl = newiTempLabel(NULL);
10022   tlbl1= newiTempLabel(NULL);
10023
10024   size = AOP_SIZE(result);
10025   offset = 1;
10026
10027   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10028
10029   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10030
10031   /* offset should be 0, 1 or 3 */
10032   
10033   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10034   emitSKPNZ;
10035   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10036
10037   pic16_emitpcode(POC_MOVWF, pctemp);
10038
10039
10040   pic16_emitpLabel(tlbl->key);
10041
10042   emitCLRC;
10043   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10044   while(--size)
10045     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10046
10047   pic16_emitpcode(POC_DECFSZ,  pctemp);
10048   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10049   pic16_emitpLabel(tlbl1->key);
10050
10051   pic16_popReleaseTempReg(pctemp,1);
10052
10053
10054  release:
10055   pic16_freeAsmop (right,NULL,ic,TRUE);
10056   pic16_freeAsmop(left,NULL,ic,TRUE);
10057   pic16_freeAsmop(result,NULL,ic,TRUE);
10058 }
10059 #endif
10060
10061 /*-----------------------------------------------------------------*/
10062 /* genrshOne - right shift a one byte quantity by known count      */
10063 /*-----------------------------------------------------------------*/
10064 static void genrshOne (operand *result, operand *left,
10065                        int shCount, int sign)
10066 {
10067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10068     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10069 }
10070
10071 /*-----------------------------------------------------------------*/
10072 /* genrshTwo - right shift two bytes by known amount != 0          */
10073 /*-----------------------------------------------------------------*/
10074 static void genrshTwo (operand *result,operand *left,
10075                        int shCount, int sign)
10076 {
10077   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10078   /* if shCount >= 8 */
10079   if (shCount >= 8) {
10080     shCount -= 8 ;
10081     if (shCount)
10082       shiftR1Left2Result(left, MSB16, result, LSB,
10083                          shCount, sign);
10084     else
10085       movLeft2Result(left, MSB16, result, LSB);
10086
10087     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10088
10089     if(sign) {
10090       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10091       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10092     }
10093   }
10094
10095   /*  1 <= shCount <= 7 */
10096   else
10097     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10098 }
10099
10100 /*-----------------------------------------------------------------*/
10101 /* shiftRLong - shift right one long from left to result           */
10102 /* offl = LSB or MSB16                                             */
10103 /*-----------------------------------------------------------------*/
10104 static void shiftRLong (operand *left, int offl,
10105                         operand *result, int sign)
10106 {
10107     int size = AOP_SIZE(result);
10108     int same = pic16_sameRegs(AOP(left),AOP(result));
10109     int i;
10110     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10111
10112         if (same && (offl == MSB16)) { //shift one byte right
10113                 for(i=MSB16;i<size;i++) {
10114                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10115                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10116                 }
10117         }
10118
10119     if(sign)
10120                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10121         else
10122                 emitCLRC;
10123
10124         if (same) {
10125                 if (offl == LSB)
10126                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10127         } else {
10128         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10129         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10130         }
10131
10132     if(offl == MSB16) {
10133         /* add sign of "a" */
10134         pic16_addSign(result, MSB32, sign);
10135         }
10136
10137         if (same) {
10138         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10139         } else {
10140         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10141         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10142         }
10143         
10144         if (same) {
10145         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10146         } else {
10147         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10148         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10149         }
10150
10151         if (same) {
10152         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10153         } else {
10154         if(offl == LSB){
10155                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10156                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10157         }
10158         }
10159 }
10160
10161 /*-----------------------------------------------------------------*/
10162 /* genrshFour - shift four byte by a known amount != 0             */
10163 /*-----------------------------------------------------------------*/
10164 static void genrshFour (operand *result, operand *left,
10165                         int shCount, int sign)
10166 {
10167   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10168   /* if shifting more that 3 bytes */
10169   if(shCount >= 24 ) {
10170     shCount -= 24;
10171     if(shCount)
10172       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10173     else
10174       movLeft2Result(left, MSB32, result, LSB);
10175
10176     pic16_addSign(result, MSB16, sign);
10177   }
10178   else if(shCount >= 16){
10179     shCount -= 16;
10180     if(shCount)
10181       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10182     else{
10183       movLeft2Result(left, MSB24, result, LSB);
10184       movLeft2Result(left, MSB32, result, MSB16);
10185     }
10186     pic16_addSign(result, MSB24, sign);
10187   }
10188   else if(shCount >= 8){
10189     shCount -= 8;
10190     if(shCount == 1)
10191       shiftRLong(left, MSB16, result, sign);
10192     else if(shCount == 0){
10193       movLeft2Result(left, MSB16, result, LSB);
10194       movLeft2Result(left, MSB24, result, MSB16);
10195       movLeft2Result(left, MSB32, result, MSB24);
10196       pic16_addSign(result, MSB32, sign);
10197     }
10198     else{ //shcount >= 2
10199       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10200       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10201       /* the last shift is signed */
10202       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10203       pic16_addSign(result, MSB32, sign);
10204     }
10205   }
10206   else{   /* 1 <= shCount <= 7 */
10207     if(shCount <= 2){
10208       shiftRLong(left, LSB, result, sign);
10209       if(shCount == 2)
10210         shiftRLong(result, LSB, result, sign);
10211     }
10212     else{
10213       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10214       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10215       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10216     }
10217   }
10218 }
10219
10220 /*-----------------------------------------------------------------*/
10221 /* genRightShiftLiteral - right shifting by known count            */
10222 /*-----------------------------------------------------------------*/
10223 static void genRightShiftLiteral (operand *left,
10224                                   operand *right,
10225                                   operand *result,
10226                                   iCode *ic,
10227                                   int sign)
10228 {    
10229   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10230   int lsize,res_size;
10231
10232   pic16_freeAsmop(right,NULL,ic,TRUE);
10233
10234   pic16_aopOp(left,ic,FALSE);
10235   pic16_aopOp(result,ic,FALSE);
10236
10237   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10238
10239 #if VIEW_SIZE
10240   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10241                  AOP_SIZE(left));
10242 #endif
10243
10244   lsize = pic16_getDataSize(left);
10245   res_size = pic16_getDataSize(result);
10246   /* test the LEFT size !!! */
10247
10248   /* I suppose that the left size >= result size */
10249   if(shCount == 0){
10250     while(res_size--)
10251       movLeft2Result(left, lsize, result, res_size);
10252   }
10253
10254   else if(shCount >= (lsize * 8)){
10255
10256     if(res_size == 1) {
10257       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10258       if(sign) {
10259         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10260         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10261       }
10262     } else {
10263
10264       if(sign) {
10265         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10266         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10267         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10268         while(res_size--)
10269           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10270
10271       } else {
10272
10273         while(res_size--)
10274           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10275       }
10276     }
10277   } else {
10278
10279     switch (res_size) {
10280     case 1:
10281       genrshOne (result,left,shCount,sign);
10282       break;
10283
10284     case 2:
10285       genrshTwo (result,left,shCount,sign);
10286       break;
10287
10288     case 4:
10289       genrshFour (result,left,shCount,sign);
10290       break;
10291     default :
10292       break;
10293     }
10294
10295   }
10296
10297   pic16_freeAsmop(left,NULL,ic,TRUE);
10298   pic16_freeAsmop(result,NULL,ic,TRUE);
10299 }
10300
10301 #if !(USE_GENERIC_SIGNED_SHIFT)
10302 /*-----------------------------------------------------------------*/
10303 /* genSignedRightShift - right shift of signed number              */
10304 /*-----------------------------------------------------------------*/
10305 static void genSignedRightShift (iCode *ic)
10306 {
10307   operand *right, *left, *result;
10308   int size, offset;
10309   //  char *l;
10310   symbol *tlbl, *tlbl1 ;
10311   pCodeOp *pctemp;
10312
10313   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10314
10315   /* we do it the hard way put the shift count in b
10316      and loop thru preserving the sign */
10317   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10318
10319   right = IC_RIGHT(ic);
10320   left  = IC_LEFT(ic);
10321   result = IC_RESULT(ic);
10322
10323   pic16_aopOp(right,ic,FALSE);  
10324   pic16_aopOp(left,ic,FALSE);
10325   pic16_aopOp(result,ic,FALSE);
10326
10327
10328   if ( AOP_TYPE(right) == AOP_LIT) {
10329     genRightShiftLiteral (left,right,result,ic,1);
10330     return ;
10331   }
10332   /* shift count is unknown then we have to form 
10333      a loop get the loop count in B : Note: we take
10334      only the lower order byte since shifting
10335      more that 32 bits make no sense anyway, ( the
10336      largest size of an object can be only 32 bits ) */  
10337
10338   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10339   //pic16_emitcode("inc","b");
10340   //pic16_freeAsmop (right,NULL,ic,TRUE);
10341   //pic16_aopOp(left,ic,FALSE);
10342   //pic16_aopOp(result,ic,FALSE);
10343
10344   /* now move the left to the result if they are not the
10345      same */
10346   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10347       AOP_SIZE(result) > 1) {
10348
10349     size = AOP_SIZE(result);
10350     offset=0;
10351     while (size--) { 
10352       /*
10353         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10354         if (*l == '@' && IS_AOP_PREG(result)) {
10355
10356         pic16_emitcode("mov","a,%s",l);
10357         pic16_aopPut(AOP(result),"a",offset);
10358         } else
10359         pic16_aopPut(AOP(result),l,offset);
10360       */
10361       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10362       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10363
10364       offset++;
10365     }
10366   }
10367
10368   /* mov the highest order bit to OVR */    
10369   tlbl = newiTempLabel(NULL);
10370   tlbl1= newiTempLabel(NULL);
10371
10372   size = AOP_SIZE(result);
10373   offset = size - 1;
10374
10375   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10376
10377   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10378
10379   /* offset should be 0, 1 or 3 */
10380   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10381   emitSKPNZ;
10382   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10383
10384   pic16_emitpcode(POC_MOVWF, pctemp);
10385
10386
10387   pic16_emitpLabel(tlbl->key);
10388
10389   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10390   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10391
10392   while(--size) {
10393     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10394   }
10395
10396   pic16_emitpcode(POC_DECFSZ,  pctemp);
10397   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10398   pic16_emitpLabel(tlbl1->key);
10399
10400   pic16_popReleaseTempReg(pctemp,1);
10401 #if 0
10402   size = AOP_SIZE(result);
10403   offset = size - 1;
10404   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10405   pic16_emitcode("rlc","a");
10406   pic16_emitcode("mov","ov,c");
10407   /* if it is only one byte then */
10408   if (size == 1) {
10409     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10410     MOVA(l);
10411     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10412     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10413     pic16_emitcode("mov","c,ov");
10414     pic16_emitcode("rrc","a");
10415     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10416     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10417     pic16_aopPut(AOP(result),"a",0);
10418     goto release ;
10419   }
10420
10421   reAdjustPreg(AOP(result));
10422   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10423   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10424   pic16_emitcode("mov","c,ov");
10425   while (size--) {
10426     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10427     MOVA(l);
10428     pic16_emitcode("rrc","a");         
10429     pic16_aopPut(AOP(result),"a",offset--);
10430   }
10431   reAdjustPreg(AOP(result));
10432   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10433   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10434
10435  release:
10436 #endif
10437
10438   pic16_freeAsmop(left,NULL,ic,TRUE);
10439   pic16_freeAsmop(result,NULL,ic,TRUE);
10440   pic16_freeAsmop(right,NULL,ic,TRUE);
10441 }
10442 #endif
10443
10444 #if !(USE_GENERIC_SIGNED_SHIFT)
10445 #warning This implementation of genRightShift() is incomplete!
10446 /*-----------------------------------------------------------------*/
10447 /* genRightShift - generate code for right shifting                */
10448 /*-----------------------------------------------------------------*/
10449 static void genRightShift (iCode *ic)
10450 {
10451     operand *right, *left, *result;
10452     sym_link *letype ;
10453     int size, offset;
10454     char *l;
10455     symbol *tlbl, *tlbl1 ;
10456
10457     /* if signed then we do it the hard way preserve the
10458     sign bit moving it inwards */
10459     letype = getSpec(operandType(IC_LEFT(ic)));
10460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10461
10462     if (!SPEC_USIGN(letype)) {
10463         genSignedRightShift (ic);
10464         return ;
10465     }
10466
10467     /* signed & unsigned types are treated the same : i.e. the
10468     signed is NOT propagated inwards : quoting from the
10469     ANSI - standard : "for E1 >> E2, is equivalent to division
10470     by 2**E2 if unsigned or if it has a non-negative value,
10471     otherwise the result is implementation defined ", MY definition
10472     is that the sign does not get propagated */
10473
10474     right = IC_RIGHT(ic);
10475     left  = IC_LEFT(ic);
10476     result = IC_RESULT(ic);
10477
10478     pic16_aopOp(right,ic,FALSE);
10479
10480     /* if the shift count is known then do it 
10481     as efficiently as possible */
10482     if (AOP_TYPE(right) == AOP_LIT) {
10483         genRightShiftLiteral (left,right,result,ic, 0);
10484         return ;
10485     }
10486
10487     /* shift count is unknown then we have to form 
10488     a loop get the loop count in B : Note: we take
10489     only the lower order byte since shifting
10490     more that 32 bits make no sense anyway, ( the
10491     largest size of an object can be only 32 bits ) */  
10492
10493     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10494     pic16_emitcode("inc","b");
10495     pic16_aopOp(left,ic,FALSE);
10496     pic16_aopOp(result,ic,FALSE);
10497
10498     /* now move the left to the result if they are not the
10499     same */
10500     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10501         AOP_SIZE(result) > 1) {
10502
10503         size = AOP_SIZE(result);
10504         offset=0;
10505         while (size--) {
10506             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10507             if (*l == '@' && IS_AOP_PREG(result)) {
10508
10509                 pic16_emitcode("mov","a,%s",l);
10510                 pic16_aopPut(AOP(result),"a",offset);
10511             } else
10512                 pic16_aopPut(AOP(result),l,offset);
10513             offset++;
10514         }
10515     }
10516
10517     tlbl = newiTempLabel(NULL);
10518     tlbl1= newiTempLabel(NULL);
10519     size = AOP_SIZE(result);
10520     offset = size - 1;
10521
10522     /* if it is only one byte then */
10523     if (size == 1) {
10524
10525       tlbl = newiTempLabel(NULL);
10526       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10527         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10528         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10529       }
10530
10531       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10532       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10533       pic16_emitpLabel(tlbl->key);
10534       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10535       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10536       emitSKPC;
10537       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10538
10539       goto release ;
10540     }
10541
10542     reAdjustPreg(AOP(result));
10543     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10544     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10545     CLRC;
10546     while (size--) {
10547         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10548         MOVA(l);
10549         pic16_emitcode("rrc","a");         
10550         pic16_aopPut(AOP(result),"a",offset--);
10551     }
10552     reAdjustPreg(AOP(result));
10553
10554     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10555     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10556
10557 release:
10558     pic16_freeAsmop(left,NULL,ic,TRUE);
10559     pic16_freeAsmop (right,NULL,ic,TRUE);
10560     pic16_freeAsmop(result,NULL,ic,TRUE);
10561 }
10562 #endif
10563
10564 #if (USE_GENERIC_SIGNED_SHIFT)
10565 /*-----------------------------------------------------------------*/
10566 /* genGenericShift - generates code for left or right shifting     */
10567 /*-----------------------------------------------------------------*/
10568 static void genGenericShift (iCode *ic, int isShiftLeft) {
10569   operand *left,*right, *result;
10570   int offset;
10571   int sign, signedCount;
10572   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10573   PIC_OPCODE pos_shift, neg_shift;
10574
10575   FENTRY;
10576
10577   right = IC_RIGHT(ic);
10578   left  = IC_LEFT(ic);
10579   result = IC_RESULT(ic);
10580
10581   pic16_aopOp(right,ic,FALSE);
10582   pic16_aopOp(left,ic,FALSE);
10583   pic16_aopOp(result,ic,FALSE);
10584
10585   sign = !SPEC_USIGN(operandType (left));
10586   signedCount = !SPEC_USIGN(operandType (right));
10587
10588   /* if the shift count is known then do it 
10589      as efficiently as possible */
10590   if (AOP_TYPE(right) == AOP_LIT) {
10591     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10592     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10593     // we should modify right->aopu.aop_lit here!
10594     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10595     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10596     if (isShiftLeft)
10597       pic16_genLeftShiftLiteral (left,right,result,ic);
10598     else
10599       genRightShiftLiteral (left,right,result,ic, sign);
10600
10601     goto release;
10602   } // if (right is literal)
10603
10604   /* shift count is unknown then we have to form a loop.
10605    * Note: we take only the lower order byte since shifting
10606    * more than 32 bits make no sense anyway, ( the
10607    * largest size of an object can be only 32 bits )
10608    * Note: we perform arithmetic shifts if the left operand is
10609    * signed and we do an (effective) right shift, i. e. we
10610    * shift in the sign bit from the left. */
10611    
10612   label_complete = newiTempLabel ( NULL );
10613   label_loop_pos = newiTempLabel ( NULL );
10614   label_loop_neg = NULL;
10615   label_negative = NULL;
10616   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10617   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10618
10619   if (signedCount) {
10620     // additional labels needed
10621     label_loop_neg = newiTempLabel ( NULL );
10622     label_negative = newiTempLabel ( NULL );
10623   } // if
10624
10625   // copy source to result -- this will effectively truncate the left operand to the size of result!
10626   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10627   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10628   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10629     mov2f (AOP(result),AOP(left), offset);
10630   } // for
10631
10632   // if result is longer than left, fill with zeros (or sign)
10633   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10634     if (sign && AOP_SIZE(left) > 0) {
10635       // shift signed operand -- fill with sign
10636       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10637       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10638       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10639       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10640         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10641       } // for
10642     } else {
10643       // shift unsigned operand -- fill result with zeros
10644       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10645         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10646       } // for
10647     }
10648   } // if (size mismatch)
10649
10650   pic16_mov2w (AOP(right), 0);
10651   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10652   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10653   
10654 #if 0
10655   // perform a shift by one (shift count is positive)
10656   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10657   // 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])
10658   pic16_emitpLabel (label_loop_pos->key);
10659   emitCLRC;
10660   if (sign && (pos_shift == POC_RRCF)) {
10661     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10662     emitSETC;
10663   } // if
10664   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10665   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10666   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10667 #else
10668   // perform a shift by one (shift count is positive)
10669   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10670   // 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])
10671   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10672   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10673   emitCLRC;
10674   pic16_emitpLabel (label_loop_pos->key);
10675   if (sign && (pos_shift == POC_RRCF)) {
10676     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10677     emitSETC;
10678   } // if
10679   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10680   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10681   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10682   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10683 #endif
10684
10685   if (signedCount) {
10686     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10687
10688     pic16_emitpLabel (label_negative->key);
10689     // perform a shift by -1 (shift count is negative)
10690     // 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)
10691     emitCLRC;
10692     pic16_emitpLabel (label_loop_neg->key);
10693     if (sign && (neg_shift == POC_RRCF)) {
10694       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10695       emitSETC;
10696     } // if
10697     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10698     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10699     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10700     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10701   } // if (signedCount)
10702
10703   pic16_emitpLabel (label_complete->key);
10704
10705 release:
10706   pic16_freeAsmop (right,NULL,ic,TRUE);
10707   pic16_freeAsmop(left,NULL,ic,TRUE);
10708   pic16_freeAsmop(result,NULL,ic,TRUE);
10709 }
10710
10711 static void genLeftShift (iCode *ic) {
10712   genGenericShift (ic, 1);
10713 }
10714
10715 static void genRightShift (iCode *ic) {
10716   genGenericShift (ic, 0);
10717 }
10718 #endif
10719
10720
10721 void pic16_loadFSR0(operand *op)
10722 {
10723         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10724 }
10725
10726 /*-----------------------------------------------------------------*/
10727 /* genUnpackBits - generates code for unpacking bits               */
10728 /*-----------------------------------------------------------------*/
10729 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10730 {    
10731   int shCnt ;
10732   int rlen = 0 ;
10733   sym_link *etype, *letype;
10734   int blen=0, bstr=0;
10735   int lbstr;
10736   int offset = 0 ;
10737
10738     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10739     etype = getSpec(operandType(result));
10740     letype = getSpec(operandType(left));
10741     
10742 //    if(IS_BITFIELD(etype)) {
10743       blen = SPEC_BLEN(etype);
10744       bstr = SPEC_BSTR(etype);
10745 //    }
10746
10747     lbstr = SPEC_BSTR( letype );
10748
10749 #if 1
10750     if((blen == 1) && (bstr < 8)) {
10751       /* it is a single bit, so use the appropriate bit instructions */
10752       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10753
10754       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10755       
10756       if((ptype == POINTER) && (result)) {
10757         /* workaround to reduce the extra lfsr instruction */
10758         pic16_emitpcode(POC_BTFSC,
10759               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10760       } else {
10761         pic16_emitpcode(POC_BTFSC,
10762               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10763       }
10764         
10765       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10766
10767       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10768       return;
10769     }
10770
10771 #endif
10772
10773         /* the following call to pic16_loadFSR0 is temporary until
10774          * optimization to handle single bit assignments is added
10775          * to the function. Until then use the old safe way! -- VR */
10776         pic16_loadFSR0( left );
10777  
10778         /* read the first byte  */
10779         switch (ptype) {
10780                 case POINTER:
10781                 case IPOINTER:
10782                 case PPOINTER:
10783                 case FPOINTER:
10784                 case GPOINTER:
10785                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10786                         break;
10787                 case CPOINTER:
10788                         pic16_emitcode("clr","a");
10789                         pic16_emitcode("movc","a","@a+dptr");
10790                         break;
10791         }
10792         
10793
10794         /* if we have bitdisplacement then it fits   */
10795         /* into this byte completely or if length is */
10796         /* less than a byte                          */
10797         if ((shCnt = SPEC_BSTR(etype)) || 
10798                 (SPEC_BLEN(etype) <= 8))  {
10799
10800                 /* shift right acc */
10801                 AccRsh(shCnt, 0);
10802
10803                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10804                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10805
10806 /* VR -- normally I would use the following, but since we use the hack,
10807  * to avoid the masking from AccRsh, why not mask it right now? */
10808
10809 /*
10810                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10811 */
10812
10813                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10814           return ;
10815         }
10816
10817
10818
10819         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10820         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10821         exit(-1);
10822
10823     /* bit field did not fit in a byte  */
10824     rlen = SPEC_BLEN(etype) - 8;
10825     pic16_aopPut(AOP(result),"a",offset++);
10826
10827     while (1)  {
10828
10829         switch (ptype) {
10830         case POINTER:
10831         case IPOINTER:
10832             pic16_emitcode("inc","%s",rname);
10833             pic16_emitcode("mov","a,@%s",rname);
10834             break;
10835             
10836         case PPOINTER:
10837             pic16_emitcode("inc","%s",rname);
10838             pic16_emitcode("movx","a,@%s",rname);
10839             break;
10840
10841         case FPOINTER:
10842             pic16_emitcode("inc","dptr");
10843             pic16_emitcode("movx","a,@dptr");
10844             break;
10845             
10846         case CPOINTER:
10847             pic16_emitcode("clr","a");
10848             pic16_emitcode("inc","dptr");
10849             pic16_emitcode("movc","a","@a+dptr");
10850             break;
10851             
10852         case GPOINTER:
10853             pic16_emitcode("inc","dptr");
10854             pic16_emitcode("lcall","__gptrget");
10855             break;
10856         }
10857
10858         rlen -= 8;            
10859         /* if we are done */
10860         if ( rlen <= 0 )
10861             break ;
10862         
10863         pic16_aopPut(AOP(result),"a",offset++);
10864                               
10865     }
10866     
10867     if (rlen) {
10868         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10869         pic16_aopPut(AOP(result),"a",offset);          
10870     }
10871     
10872     return ;
10873 }
10874
10875
10876 static void genDataPointerGet(operand *left,
10877                               operand *result,
10878                               iCode *ic)
10879 {
10880   int size, offset = 0, leoffset=0 ;
10881
10882         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10883         pic16_aopOp(result, ic, FALSE);
10884
10885         size = AOP_SIZE(result);
10886 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10887
10888
10889 #if 0
10890         /* The following tests may save a redudant movff instruction when
10891          * accessing unions */
10892          
10893         /* if they are the same */
10894         if (operandsEqu (left, result)) {
10895                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10896                 goto release;
10897         }
10898 #endif
10899
10900 #if 0
10901         /* if they are the same registers */
10902         if (pic16_sameRegs(AOP(left),AOP(result))) {
10903                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10904                 goto release;
10905         }
10906 #endif
10907
10908 #if 1
10909         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10910                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10911                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10912                 goto release;
10913         }
10914 #endif
10915
10916
10917 #if 0
10918         if ( AOP_TYPE(left) == AOP_PCODE) {
10919                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10920                                 AOP(left)->aopu.pcop->name,
10921                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10922                                 PCOR(AOP(left)->aopu.pcop)->instance:
10923                                 PCOI(AOP(left)->aopu.pcop)->offset);
10924         }
10925 #endif
10926
10927         if(AOP(left)->aopu.pcop->type == PO_DIR)
10928                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10929
10930         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10931
10932         while (size--) {
10933                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10934                 
10935                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10936                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10937                         pic16_mov2w(AOP(left), offset); // patch 8
10938                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10939                 } else {
10940                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10941                                 pic16_popGet(AOP(left), offset), //patch 8
10942                                 pic16_popGet(AOP(result), offset)));
10943                 }
10944
10945                 offset++;
10946                 leoffset++;
10947         }
10948
10949 release:
10950     pic16_freeAsmop(result,NULL,ic,TRUE);
10951 }
10952
10953
10954
10955 /*-----------------------------------------------------------------*/
10956 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10957 /*-----------------------------------------------------------------*/
10958 static void genNearPointerGet (operand *left, 
10959                                operand *result, 
10960                                iCode *ic)
10961 {
10962   asmop *aop = NULL;
10963   //regs *preg = NULL ;
10964   sym_link *rtype, *retype;
10965   sym_link *ltype = operandType(left);    
10966
10967     FENTRY;
10968     
10969     rtype = operandType(result);
10970     retype= getSpec(rtype);
10971     
10972     pic16_aopOp(left,ic,FALSE);
10973
10974 //    pic16_DumpOp("(left)",left);
10975 //    pic16_DumpOp("(result)",result);
10976
10977     /* if left is rematerialisable and
10978      * result is not bit variable type and
10979      * the left is pointer to data space i.e
10980      * lower 128 bytes of space */
10981     
10982     if (AOP_TYPE(left) == AOP_PCODE
10983       && !IS_BITFIELD(retype)
10984       && DCL_TYPE(ltype) == POINTER) {
10985
10986         genDataPointerGet (left,result,ic);
10987         pic16_freeAsmop(left, NULL, ic, TRUE);
10988         return ;
10989     }
10990     
10991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10992
10993     /* if the value is already in a pointer register
10994      * then don't need anything more */
10995     if (!AOP_INPREG(AOP(left))) {
10996       /* otherwise get a free pointer register */
10997       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10998                 
10999       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11000       /* bitfields will be handled by genUnpackBits */
11001       if(!IS_BITFIELD(retype)) {
11002
11003         if(is_LitAOp( AOP(left) )) {
11004           pic16_loadFSR0( left );
11005         } else {
11006             // set up FSR0 with address from left
11007             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11008             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11009         }
11010       }
11011     }
11012 //    else
11013 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11014     
11015     pic16_aopOp (result,ic,FALSE);
11016     
11017     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11018
11019     /* if bitfield then unpack the bits */
11020     if (IS_BITFIELD(retype)) 
11021       genUnpackBits (result, left, NULL, POINTER);
11022     else {
11023       /* we have can just get the values */
11024       int size = AOP_SIZE(result);
11025       int offset = 0;   
11026         
11027       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11028
11029       /* fsr0 is loaded already -- VR */
11030 //      pic16_loadFSR0( left );
11031
11032 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11033 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11034       while(size--) {
11035         if(size) {
11036           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11037                 pic16_popGet(AOP(result), offset++)));
11038         } else {
11039           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11040                 pic16_popGet(AOP(result), offset++)));
11041         }
11042       }
11043 #if 0
11044 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11045 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11046       if(size)
11047         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11048 #endif
11049 /*
11050         while (size--) {
11051             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11052
11053                 pic16_emitcode("mov","a,@%s",rname);
11054                 pic16_aopPut(AOP(result),"a",offset);
11055             } else {
11056                 sprintf(buffer,"@%s",rname);
11057                 pic16_aopPut(AOP(result),buffer,offset);
11058             }
11059             offset++ ;
11060             if (size)
11061                 pic16_emitcode("inc","%s",rname);
11062         }
11063 */
11064     }
11065
11066     /* now some housekeeping stuff */
11067     if (aop) {
11068       /* we had to allocate for this iCode */
11069       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11070       pic16_freeAsmop(NULL,aop,ic,TRUE);
11071     } else { 
11072       /* we did not allocate which means left
11073        * already in a pointer register, then
11074        * if size > 0 && this could be used again
11075        * we have to point it back to where it 
11076        * belongs */
11077       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11078       if (AOP_SIZE(result) > 1
11079         && !OP_SYMBOL(left)->remat
11080         && ( OP_SYMBOL(left)->liveTo > ic->seq
11081             || ic->depth )) {
11082 //        int size = AOP_SIZE(result) - 1;
11083 //        while (size--)
11084 //          pic16_emitcode("dec","%s",rname);
11085         }
11086     }
11087
11088     /* done */
11089     pic16_freeAsmop(left,NULL,ic,TRUE);
11090     pic16_freeAsmop(result,NULL,ic,TRUE);
11091 }
11092
11093 /*-----------------------------------------------------------------*/
11094 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11095 /*-----------------------------------------------------------------*/
11096 static void genPagedPointerGet (operand *left, 
11097                                operand *result, 
11098                                iCode *ic)
11099 {
11100     asmop *aop = NULL;
11101     regs *preg = NULL ;
11102     char *rname ;
11103     sym_link *rtype, *retype;    
11104
11105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11106
11107     rtype = operandType(result);
11108     retype= getSpec(rtype);
11109     
11110     pic16_aopOp(left,ic,FALSE);
11111
11112   /* if the value is already in a pointer register
11113        then don't need anything more */
11114     if (!AOP_INPREG(AOP(left))) {
11115         /* otherwise get a free pointer register */
11116         aop = newAsmop(0);
11117         preg = getFreePtr(ic,&aop,FALSE);
11118         pic16_emitcode("mov","%s,%s",
11119                 preg->name,
11120                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11121         rname = preg->name ;
11122     } else
11123         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11124     
11125     pic16_freeAsmop(left,NULL,ic,TRUE);
11126     pic16_aopOp (result,ic,FALSE);
11127
11128     /* if bitfield then unpack the bits */
11129     if (IS_BITFIELD(retype)) 
11130         genUnpackBits (result,left,rname,PPOINTER);
11131     else {
11132         /* we have can just get the values */
11133         int size = AOP_SIZE(result);
11134         int offset = 0 ;        
11135         
11136         while (size--) {
11137             
11138             pic16_emitcode("movx","a,@%s",rname);
11139             pic16_aopPut(AOP(result),"a",offset);
11140             
11141             offset++ ;
11142             
11143             if (size)
11144                 pic16_emitcode("inc","%s",rname);
11145         }
11146     }
11147
11148     /* now some housekeeping stuff */
11149     if (aop) {
11150         /* we had to allocate for this iCode */
11151         pic16_freeAsmop(NULL,aop,ic,TRUE);
11152     } else { 
11153         /* we did not allocate which means left
11154            already in a pointer register, then
11155            if size > 0 && this could be used again
11156            we have to point it back to where it 
11157            belongs */
11158         if (AOP_SIZE(result) > 1 &&
11159             !OP_SYMBOL(left)->remat &&
11160             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11161               ic->depth )) {
11162             int size = AOP_SIZE(result) - 1;
11163             while (size--)
11164                 pic16_emitcode("dec","%s",rname);
11165         }
11166     }
11167
11168     /* done */
11169     pic16_freeAsmop(result,NULL,ic,TRUE);
11170     
11171         
11172 }
11173
11174 /*-----------------------------------------------------------------*/
11175 /* genFarPointerGet - gget value from far space                    */
11176 /*-----------------------------------------------------------------*/
11177 static void genFarPointerGet (operand *left,
11178                               operand *result, iCode *ic)
11179 {
11180     int size, offset ;
11181     sym_link *retype = getSpec(operandType(result));
11182
11183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11184
11185     pic16_aopOp(left,ic,FALSE);
11186
11187     /* if the operand is already in dptr 
11188     then we do nothing else we move the value to dptr */
11189     if (AOP_TYPE(left) != AOP_STR) {
11190         /* if this is remateriazable */
11191         if (AOP_TYPE(left) == AOP_IMMD)
11192             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11193         else { /* we need to get it byte by byte */
11194             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11195             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11196             if (options.model == MODEL_FLAT24)
11197             {
11198                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11199             }
11200         }
11201     }
11202     /* so dptr know contains the address */
11203     pic16_freeAsmop(left,NULL,ic,TRUE);
11204     pic16_aopOp(result,ic,FALSE);
11205
11206     /* if bit then unpack */
11207     if (IS_BITFIELD(retype)) 
11208         genUnpackBits(result,left,"dptr",FPOINTER);
11209     else {
11210         size = AOP_SIZE(result);
11211         offset = 0 ;
11212
11213         while (size--) {
11214             pic16_emitcode("movx","a,@dptr");
11215             pic16_aopPut(AOP(result),"a",offset++);
11216             if (size)
11217                 pic16_emitcode("inc","dptr");
11218         }
11219     }
11220
11221     pic16_freeAsmop(result,NULL,ic,TRUE);
11222 }
11223 #if 0
11224 /*-----------------------------------------------------------------*/
11225 /* genCodePointerGet - get value from code space                  */
11226 /*-----------------------------------------------------------------*/
11227 static void genCodePointerGet (operand *left,
11228                                 operand *result, iCode *ic)
11229 {
11230     int size, offset ;
11231     sym_link *retype = getSpec(operandType(result));
11232
11233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11234
11235     pic16_aopOp(left,ic,FALSE);
11236
11237     /* if the operand is already in dptr 
11238     then we do nothing else we move the value to dptr */
11239     if (AOP_TYPE(left) != AOP_STR) {
11240         /* if this is remateriazable */
11241         if (AOP_TYPE(left) == AOP_IMMD)
11242             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11243         else { /* we need to get it byte by byte */
11244             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11245             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11246             if (options.model == MODEL_FLAT24)
11247             {
11248                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11249             }
11250         }
11251     }
11252     /* so dptr know contains the address */
11253     pic16_freeAsmop(left,NULL,ic,TRUE);
11254     pic16_aopOp(result,ic,FALSE);
11255
11256     /* if bit then unpack */
11257     if (IS_BITFIELD(retype)) 
11258         genUnpackBits(result,left,"dptr",CPOINTER);
11259     else {
11260         size = AOP_SIZE(result);
11261         offset = 0 ;
11262
11263         while (size--) {
11264             pic16_emitcode("clr","a");
11265             pic16_emitcode("movc","a,@a+dptr");
11266             pic16_aopPut(AOP(result),"a",offset++);
11267             if (size)
11268                 pic16_emitcode("inc","dptr");
11269         }
11270     }
11271
11272     pic16_freeAsmop(result,NULL,ic,TRUE);
11273 }
11274 #endif
11275 #if 0
11276 /*-----------------------------------------------------------------*/
11277 /* genGenPointerGet - gget value from generic pointer space        */
11278 /*-----------------------------------------------------------------*/
11279 static void genGenPointerGet (operand *left,
11280                               operand *result, iCode *ic)
11281 {
11282   int size, offset, lit;
11283   sym_link *retype = getSpec(operandType(result));
11284
11285         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11286         pic16_aopOp(left,ic,FALSE);
11287         pic16_aopOp(result,ic,FALSE);
11288         size = AOP_SIZE(result);
11289
11290         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11291
11292         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11293
11294                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11295                 // load FSR0 from immediate
11296                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11297
11298 //              pic16_loadFSR0( left );
11299
11300                 offset = 0;
11301                 while(size--) {
11302                         if(size) {
11303                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11304                         } else {
11305                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11306                         }
11307                         offset++;
11308                 }
11309                 goto release;
11310
11311         }
11312         else { /* we need to get it byte by byte */
11313                 // set up FSR0 with address from left
11314                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11315                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11316
11317                 offset = 0 ;
11318
11319                 while(size--) {
11320                         if(size) {
11321                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11322                         } else {
11323                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11324                         }
11325                         offset++;
11326                 }
11327                 goto release;
11328         }
11329
11330   /* if bit then unpack */
11331         if (IS_BITFIELD(retype)) 
11332                 genUnpackBits(result,left,"BAD",GPOINTER);
11333
11334         release:
11335         pic16_freeAsmop(left,NULL,ic,TRUE);
11336         pic16_freeAsmop(result,NULL,ic,TRUE);
11337
11338 }
11339 #endif
11340
11341
11342 /*-----------------------------------------------------------------*/
11343 /* genGenPointerGet - gget value from generic pointer space        */
11344 /*-----------------------------------------------------------------*/
11345 static void genGenPointerGet (operand *left,
11346                               operand *result, iCode *ic)
11347 {
11348   int size, offset, lit;
11349   sym_link *retype = getSpec(operandType(result));
11350   char fgptrget[32];
11351
11352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11353     pic16_aopOp(left,ic,FALSE);
11354     pic16_aopOp(result,ic,FALSE);
11355     size = AOP_SIZE(result);
11356
11357     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11358
11359     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11360
11361       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11362       // load FSR0 from immediate
11363       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11364
11365       werror(W_POSSBUG2, __FILE__, __LINE__);
11366
11367       offset = 0;
11368       while(size--) {
11369         if(size) {
11370           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11371         } else {
11372           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11373         }
11374         offset++;
11375       }
11376
11377       goto release;
11378
11379     } else { /* we need to get it byte by byte */
11380
11381       /* set up WREG:PRODL:FSR0L with address from left */
11382       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11383       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11384       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11385       
11386       switch( size ) {
11387         case 1: strcpy(fgptrget, "__gptrget1"); break;
11388         case 2: strcpy(fgptrget, "__gptrget2"); break;
11389         case 3: strcpy(fgptrget, "__gptrget3"); break;
11390         case 4: strcpy(fgptrget, "__gptrget4"); break;
11391         default:
11392           werror(W_POSSBUG2, __FILE__, __LINE__);
11393           abort();
11394       }
11395       
11396       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11397       
11398       assignResultValue(result, 1);
11399       
11400       {
11401         symbol *sym;
11402
11403           sym = newSymbol( fgptrget, 0 );
11404           strcpy(sym->rname, fgptrget);
11405           checkAddSym(&externs, sym);
11406
11407 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11408       }
11409               
11410       goto release;
11411     }
11412
11413   /* if bit then unpack */
11414     if (IS_BITFIELD(retype)) 
11415       genUnpackBits(result,left,"BAD",GPOINTER);
11416
11417 release:
11418   pic16_freeAsmop(left,NULL,ic,TRUE);
11419   pic16_freeAsmop(result,NULL,ic,TRUE);
11420 }
11421
11422 /*-----------------------------------------------------------------*/
11423 /* genConstPointerGet - get value from const generic pointer space */
11424 /*-----------------------------------------------------------------*/
11425 static void genConstPointerGet (operand *left,
11426                                 operand *result, iCode *ic)
11427 {
11428   //sym_link *retype = getSpec(operandType(result));
11429   // symbol *albl = newiTempLabel(NULL);        // patch 15
11430   // symbol *blbl = newiTempLabel(NULL);        //
11431   // PIC_OPCODE poc;                            // patch 15
11432   int size;
11433   int offset = 0;
11434
11435   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11436   pic16_aopOp(left,ic,FALSE);
11437   pic16_aopOp(result,ic,TRUE);
11438   size = AOP_SIZE(result);
11439
11440   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11441
11442   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11443 #if 0                                                                   // patch 15
11444   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11445   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11446   pic16_emitpLabel(albl->key);
11447
11448   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11449   
11450   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11451   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11452   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11453   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11454   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11455
11456   pic16_emitpLabel(blbl->key);
11457
11458   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11459 #endif                                                                  // patch 15
11460
11461
11462   // set up table pointer
11463   if( (AOP_TYPE(left) == AOP_PCODE) 
11464       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11465           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11466     {
11467       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11468       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11469       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11470       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11471       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11472       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11473     }
11474   else
11475     {
11476       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11477       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11478       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11479     }
11480
11481
11482   while(size--)
11483     {
11484       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11485       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11486       offset++;
11487     }
11488     
11489   pic16_freeAsmop(left,NULL,ic,TRUE);
11490   pic16_freeAsmop(result,NULL,ic,TRUE);
11491
11492 }
11493
11494
11495 /*-----------------------------------------------------------------*/
11496 /* genPointerGet - generate code for pointer get                   */
11497 /*-----------------------------------------------------------------*/
11498 static void genPointerGet (iCode *ic)
11499 {
11500     operand *left, *result ;
11501     sym_link *type, *etype;
11502     int p_type;
11503
11504     FENTRY;
11505     
11506     left = IC_LEFT(ic);
11507     result = IC_RESULT(ic) ;
11508
11509     /* depending on the type of pointer we need to
11510     move it to the correct pointer register */
11511     type = operandType(left);
11512     etype = getSpec(type);
11513
11514 #if 0
11515     if (IS_PTR_CONST(type))
11516 #else
11517     if (IS_CODEPTR(type))
11518 #endif
11519       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11520
11521     /* if left is of type of pointer then it is simple */
11522     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11523         p_type = DCL_TYPE(type);
11524     else {
11525         /* we have to go by the storage class */
11526         p_type = PTR_TYPE(SPEC_OCLS(etype));
11527
11528         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11529
11530         if (SPEC_OCLS(etype)->codesp ) {
11531           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11532           //p_type = CPOINTER ; 
11533         }
11534         else
11535             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11536               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11537                /*p_type = FPOINTER ;*/ 
11538             else
11539                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11540                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11541 /*                  p_type = PPOINTER; */
11542                 else
11543                     if (SPEC_OCLS(etype) == idata )
11544                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11545 /*                      p_type = IPOINTER; */
11546                     else
11547                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11548 /*                      p_type = POINTER ; */
11549     }
11550
11551     /* now that we have the pointer type we assign
11552     the pointer values */
11553     switch (p_type) {
11554
11555     case POINTER:       
11556     case IPOINTER:
11557         genNearPointerGet (left,result,ic);
11558         break;
11559
11560     case PPOINTER:
11561         genPagedPointerGet(left,result,ic);
11562         break;
11563
11564     case FPOINTER:
11565         genFarPointerGet (left,result,ic);
11566         break;
11567
11568     case CPOINTER:
11569         genConstPointerGet (left,result,ic);
11570         //pic16_emitcodePointerGet (left,result,ic);
11571         break;
11572
11573     case GPOINTER:
11574 #if 0
11575       if (IS_PTR_CONST(type))
11576         genConstPointerGet (left,result,ic);
11577       else
11578 #endif
11579         genGenPointerGet (left,result,ic);
11580       break;
11581
11582     default:
11583       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11584               "genPointerGet: illegal pointer type");
11585     
11586     }
11587
11588 }
11589
11590 /*-----------------------------------------------------------------*/
11591 /* genPackBits - generates code for packed bit storage             */
11592 /*-----------------------------------------------------------------*/
11593 static void genPackBits (sym_link    *etype , operand *result,
11594                          operand *right ,
11595                          char *rname, int p_type)
11596 {
11597   int shCnt = 0 ;
11598   int offset = 0  ;
11599   int rLen = 0 ;
11600   int blen, bstr ;   
11601   sym_link *retype;
11602   char *l ;
11603
11604         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11605         blen = SPEC_BLEN(etype);
11606         bstr = SPEC_BSTR(etype);
11607
11608         retype = getSpec(operandType(right));
11609
11610         if(AOP_TYPE(right) == AOP_LIT) {
11611                 if((blen == 1) && (bstr < 8)) {
11612                   unsigned long lit;
11613                         /* it is a single bit, so use the appropriate bit instructions */
11614
11615                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11616
11617                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11618 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11619                         if((p_type == POINTER) && (result)) {
11620                                 /* workaround to reduce the extra lfsr instruction */
11621                                 if(lit) {
11622                                         pic16_emitpcode(POC_BSF,
11623                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11624                                 } else {
11625                                         pic16_emitpcode(POC_BCF,
11626                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11627                                 }
11628                         } else {
11629                                 pic16_loadFSR0( result );
11630                                 if(lit) {
11631                                         pic16_emitpcode(POC_BSF,
11632                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11633                                 } else {
11634                                         pic16_emitpcode(POC_BCF,
11635                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11636                                 }
11637                         }
11638         
11639                   return;
11640                 }
11641
11642                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11643                 offset++;
11644         } else
11645         if(IS_BITFIELD(retype) 
11646           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11647           && (blen == 1)) {
11648           int rblen, rbstr;
11649
11650             rblen = SPEC_BLEN( retype );
11651             rbstr = SPEC_BSTR( retype );
11652             
11653
11654             if(IS_BITFIELD(etype)) {
11655               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11656               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11657             } else {
11658               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11659             }
11660             
11661             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11662             
11663             if(IS_BITFIELD(etype)) {
11664               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11665             } else {
11666               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11667             }
11668
11669             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11670             
11671             return;
11672         } else
11673           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11674
11675         /* if the bit lenth is less than or    */
11676         /* it exactly fits a byte then         */
11677         if((shCnt=SPEC_BSTR(etype))
11678                 || SPEC_BLEN(etype) <= 8 )  {
11679
11680                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11681
11682                 /* shift left acc */
11683                 AccLsh(shCnt);
11684
11685                 /* using PRODL as a temporary register here */
11686                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11687
11688                 switch (p_type) {
11689                         case FPOINTER:
11690                         case POINTER:
11691                                 pic16_loadFSR0( result );
11692                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11693 //                              pic16_emitcode ("mov","b,a");
11694 //                              pic16_emitcode("mov","a,@%s",rname);
11695                                 break;
11696
11697                         case GPOINTER:
11698                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11699                                 break;
11700
11701                 }
11702 #if 1
11703                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11704                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11705                                         (unsigned char)(0xff >> (8-bstr))) ));
11706                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11707                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11708 #endif
11709
11710           return;
11711         }
11712
11713
11714         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11715         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11716         exit(-1);
11717
11718
11719     /* if we r done */
11720     if ( SPEC_BLEN(etype) <= 8 )
11721         return ;
11722
11723     pic16_emitcode("inc","%s",rname);
11724     rLen = SPEC_BLEN(etype) ;     
11725
11726
11727
11728     /* now generate for lengths greater than one byte */
11729     while (1) {
11730
11731         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11732
11733         rLen -= 8 ;
11734         if (rLen <= 0 )
11735             break ;
11736
11737         switch (p_type) {
11738             case POINTER:
11739                 if (*l == '@') {
11740                     MOVA(l);
11741                     pic16_emitcode("mov","@%s,a",rname);
11742                 } else
11743                     pic16_emitcode("mov","@%s,%s",rname,l);
11744                 break;
11745
11746             case FPOINTER:
11747                 MOVA(l);
11748                 pic16_emitcode("movx","@dptr,a");
11749                 break;
11750
11751             case GPOINTER:
11752                 MOVA(l);
11753                 DEBUGpic16_emitcode(";lcall","__gptrput");
11754                 break;  
11755         }   
11756         pic16_emitcode ("inc","%s",rname);
11757     }
11758
11759     MOVA(l);
11760
11761     /* last last was not complete */
11762     if (rLen)   {
11763         /* save the byte & read byte */
11764         switch (p_type) {
11765             case POINTER:
11766                 pic16_emitcode ("mov","b,a");
11767                 pic16_emitcode("mov","a,@%s",rname);
11768                 break;
11769
11770             case FPOINTER:
11771                 pic16_emitcode ("mov","b,a");
11772                 pic16_emitcode("movx","a,@dptr");
11773                 break;
11774
11775             case GPOINTER:
11776                 pic16_emitcode ("push","b");
11777                 pic16_emitcode ("push","acc");
11778                 pic16_emitcode ("lcall","__gptrget");
11779                 pic16_emitcode ("pop","b");
11780                 break;
11781         }
11782
11783         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11784         pic16_emitcode ("orl","a,b");
11785     }
11786
11787     if (p_type == GPOINTER)
11788         pic16_emitcode("pop","b");
11789
11790     switch (p_type) {
11791
11792     case POINTER:
11793         pic16_emitcode("mov","@%s,a",rname);
11794         break;
11795         
11796     case FPOINTER:
11797         pic16_emitcode("movx","@dptr,a");
11798         break;
11799         
11800     case GPOINTER:
11801         DEBUGpic16_emitcode(";lcall","__gptrput");
11802         break;                  
11803     }
11804 }
11805 /*-----------------------------------------------------------------*/
11806 /* genDataPointerSet - remat pointer to data space                 */
11807 /*-----------------------------------------------------------------*/
11808 static void genDataPointerSet(operand *right,
11809                               operand *result,
11810                               iCode *ic)
11811 {
11812     int size, offset = 0, resoffset=0 ;
11813
11814     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11815     pic16_aopOp(right,ic,FALSE);
11816
11817     size = AOP_SIZE(right);
11818
11819 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11820
11821 #if 0
11822     if ( AOP_TYPE(result) == AOP_PCODE) {
11823       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11824               AOP(result)->aopu.pcop->name,
11825                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11826               PCOR(AOP(result)->aopu.pcop)->instance:
11827               PCOI(AOP(result)->aopu.pcop)->offset);
11828     }
11829 #endif
11830
11831         if(AOP(result)->aopu.pcop->type == PO_DIR)
11832                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11833
11834         while (size--) {
11835                 if (AOP_TYPE(right) == AOP_LIT) {
11836                   unsigned int lit;
11837
11838                     if(!IS_FLOAT(operandType( right )))
11839                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11840                     else {
11841                       union {
11842                         unsigned long lit_int;
11843                         float lit_float;
11844                       } info;
11845         
11846                         /* take care if literal is a float */
11847                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11848                         lit = info.lit_int;
11849                     }
11850
11851                     lit = lit >> (8*offset);
11852                     if(lit&0xff) {
11853                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11854                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11855                     } else {
11856                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11857                     }
11858                 } else {
11859                   pic16_mov2w(AOP(right), offset);
11860                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11861                 }
11862                 offset++;
11863                 resoffset++;
11864         }
11865
11866     pic16_freeAsmop(right,NULL,ic,TRUE);
11867 }
11868
11869
11870
11871 /*-----------------------------------------------------------------*/
11872 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11873 /*-----------------------------------------------------------------*/
11874 static void genNearPointerSet (operand *right,
11875                                operand *result, 
11876                                iCode *ic)
11877 {
11878   asmop *aop = NULL;
11879   char *l;
11880   sym_link *retype;
11881   sym_link *ptype = operandType(result);
11882   sym_link *resetype;
11883     
11884         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11885         retype= getSpec(operandType(right));
11886         resetype = getSpec(operandType(result));
11887   
11888         pic16_aopOp(result,ic,FALSE);
11889     
11890         /* if the result is rematerializable &
11891          * in data space & not a bit variable */
11892         
11893         /* and result is not a bit variable */
11894         if (AOP_TYPE(result) == AOP_PCODE
11895 //              && AOP_TYPE(result) == AOP_IMMD
11896                 && DCL_TYPE(ptype) == POINTER
11897                 && !IS_BITFIELD(retype)
11898                 && !IS_BITFIELD(resetype)) {
11899
11900                 genDataPointerSet (right,result,ic);
11901                 pic16_freeAsmop(result,NULL,ic,TRUE);
11902           return;
11903         }
11904
11905         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11906         pic16_aopOp(right,ic,FALSE);
11907         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11908
11909         /* if the value is already in a pointer register
11910          * then don't need anything more */
11911         if (!AOP_INPREG(AOP(result))) {
11912                 /* otherwise get a free pointer register */
11913                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11914
11915 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11916 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11917 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11918                 if(is_LitAOp( AOP(result) ))
11919                 {
11920                   if(!IS_BITFIELD(resetype))
11921                         pic16_loadFSR0( result );  // patch 10
11922                 } else {
11923                   if(!IS_BITFIELD(resetype)) {
11924                         // set up FSR0 with address of result
11925                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11926                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11927                   }
11928                 }
11929
11930         }
11931 //      else
11932 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11933
11934         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11935
11936 //      pic16_loadFSR0( result );
11937
11938         /* if bitfield then unpack the bits */
11939         if (IS_BITFIELD(resetype)) {
11940                 genPackBits (resetype, result, right, NULL, POINTER);
11941         } else {
11942                 /* we have can just get the values */
11943           int size = AOP_SIZE(right);
11944           int offset = 0 ;    
11945
11946                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11947                 while (size--) {
11948                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11949                         if (*l == '@' ) {
11950                                 //MOVA(l);
11951                                 //pic16_emitcode("mov","@%s,a",rname);
11952                                 pic16_emitcode("movf","indf0,w ;1");
11953                         } else {
11954
11955                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11956                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11957                                         if (size) {                                                                     // 
11958                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11959                                         } else {                                                                        // 
11960                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11961                                         }                                                                               // 
11962                                 } else { // no literal                                                                  // 
11963                                         if(size) {                                                                      // 
11964                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11965                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11966                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11967                                         } else {                                                                        // 
11968                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11969                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11970                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11971                                         }                                                                               //
11972                                 }                                                                                       // patch 10
11973                         }
11974                         offset++;
11975                 }
11976         }
11977
11978         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11979         /* now some housekeeping stuff */
11980         if (aop) {
11981                 /* we had to allocate for this iCode */
11982                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11983         } else { 
11984                 /* we did not allocate which means left
11985                  * already in a pointer register, then
11986                  * if size > 0 && this could be used again
11987                  * we have to point it back to where it 
11988                  * belongs */
11989                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11990                 if (AOP_SIZE(right) > 1
11991                         && !OP_SYMBOL(result)->remat
11992                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11993                                 || ic->depth )) {
11994
11995                   int size = AOP_SIZE(right) - 1;
11996
11997                         while (size--)
11998                                 pic16_emitcode("decf","fsr0,f");
11999                         //pic16_emitcode("dec","%s",rname);
12000                 }
12001         }
12002
12003         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004         /* done */
12005 //release:
12006         pic16_freeAsmop(right,NULL,ic,TRUE);
12007         pic16_freeAsmop(result,NULL,ic,TRUE);
12008 }
12009
12010 /*-----------------------------------------------------------------*/
12011 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12012 /*-----------------------------------------------------------------*/
12013 static void genPagedPointerSet (operand *right,
12014                                operand *result, 
12015                                iCode *ic)
12016 {
12017     asmop *aop = NULL;
12018     regs *preg = NULL ;
12019     char *rname , *l;
12020     sym_link *retype;
12021        
12022     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12023
12024     retype= getSpec(operandType(right));
12025     
12026     pic16_aopOp(result,ic,FALSE);
12027     
12028     /* if the value is already in a pointer register
12029        then don't need anything more */
12030     if (!AOP_INPREG(AOP(result))) {
12031         /* otherwise get a free pointer register */
12032         aop = newAsmop(0);
12033         preg = getFreePtr(ic,&aop,FALSE);
12034         pic16_emitcode("mov","%s,%s",
12035                 preg->name,
12036                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12037         rname = preg->name ;
12038     } else
12039         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12040     
12041     pic16_freeAsmop(result,NULL,ic,TRUE);
12042     pic16_aopOp (right,ic,FALSE);
12043
12044     /* if bitfield then unpack the bits */
12045     if (IS_BITFIELD(retype)) 
12046         genPackBits (retype,result,right,rname,PPOINTER);
12047     else {
12048         /* we have can just get the values */
12049         int size = AOP_SIZE(right);
12050         int offset = 0 ;        
12051         
12052         while (size--) {
12053             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12054             
12055             MOVA(l);
12056             pic16_emitcode("movx","@%s,a",rname);
12057
12058             if (size)
12059                 pic16_emitcode("inc","%s",rname);
12060
12061             offset++;
12062         }
12063     }
12064     
12065     /* now some housekeeping stuff */
12066     if (aop) {
12067         /* we had to allocate for this iCode */
12068         pic16_freeAsmop(NULL,aop,ic,TRUE);
12069     } else { 
12070         /* we did not allocate which means left
12071            already in a pointer register, then
12072            if size > 0 && this could be used again
12073            we have to point it back to where it 
12074            belongs */
12075         if (AOP_SIZE(right) > 1 &&
12076             !OP_SYMBOL(result)->remat &&
12077             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12078               ic->depth )) {
12079             int size = AOP_SIZE(right) - 1;
12080             while (size--)
12081                 pic16_emitcode("dec","%s",rname);
12082         }
12083     }
12084
12085     /* done */
12086     pic16_freeAsmop(right,NULL,ic,TRUE);
12087     
12088         
12089 }
12090
12091 /*-----------------------------------------------------------------*/
12092 /* genFarPointerSet - set value from far space                     */
12093 /*-----------------------------------------------------------------*/
12094 static void genFarPointerSet (operand *right,
12095                               operand *result, iCode *ic)
12096 {
12097     int size, offset ;
12098     sym_link *retype = getSpec(operandType(right));
12099
12100     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12101     pic16_aopOp(result,ic,FALSE);
12102
12103     /* if the operand is already in dptr 
12104     then we do nothing else we move the value to dptr */
12105     if (AOP_TYPE(result) != AOP_STR) {
12106         /* if this is remateriazable */
12107         if (AOP_TYPE(result) == AOP_IMMD)
12108             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12109         else { /* we need to get it byte by byte */
12110             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12111             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12112             if (options.model == MODEL_FLAT24)
12113             {
12114                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12115             }
12116         }
12117     }
12118     /* so dptr know contains the address */
12119     pic16_freeAsmop(result,NULL,ic,TRUE);
12120     pic16_aopOp(right,ic,FALSE);
12121
12122     /* if bit then unpack */
12123     if (IS_BITFIELD(retype)) 
12124         genPackBits(retype,result,right,"dptr",FPOINTER);
12125     else {
12126         size = AOP_SIZE(right);
12127         offset = 0 ;
12128
12129         while (size--) {
12130             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12131             MOVA(l);
12132             pic16_emitcode("movx","@dptr,a");
12133             if (size)
12134                 pic16_emitcode("inc","dptr");
12135         }
12136     }
12137
12138     pic16_freeAsmop(right,NULL,ic,TRUE);
12139 }
12140
12141 /*-----------------------------------------------------------------*/
12142 /* genGenPointerSet - set value from generic pointer space         */
12143 /*-----------------------------------------------------------------*/
12144 #if 0
12145 static void genGenPointerSet (operand *right,
12146                               operand *result, iCode *ic)
12147 {
12148         int i, size, offset, lit;
12149         sym_link *retype = getSpec(operandType(right));
12150
12151         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12152
12153         pic16_aopOp(result,ic,FALSE);
12154         pic16_aopOp(right,ic,FALSE);
12155         size = AOP_SIZE(right);
12156         offset = 0;
12157
12158         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12159
12160         /* if the operand is already in dptr 
12161                 then we do nothing else we move the value to dptr */
12162         if (AOP_TYPE(result) != AOP_STR) {
12163                 /* if this is remateriazable */
12164                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12165                 // WARNING: anythig until "else" is untested!
12166                 if (AOP_TYPE(result) == AOP_IMMD) {
12167                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12168                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12169                         // load FSR0 from immediate
12170                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12171                         offset = 0;
12172                         while(size--) {
12173                                 if(size) {
12174                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12175                                 } else {
12176                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12177                                 }
12178                                 offset++;
12179                         }
12180                         goto release;
12181                 }
12182                 else { /* we need to get it byte by byte */
12183                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12184                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12185
12186                         // set up FSR0 with address of result
12187                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12188                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12189
12190                         /* hack hack! see if this the FSR. If so don't load W */
12191                         if(AOP_TYPE(right) != AOP_ACC) {
12192
12193                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12194
12195                                 if(AOP_TYPE(right) == AOP_LIT)
12196                                 {
12197                                         // copy literal
12198                                         // note: pic16_popGet handles sign extension
12199                                         for(i=0;i<size;i++) {
12200                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12201                                                 if(i < size-1)
12202                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12203                                                 else
12204                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12205                                         }
12206                                 } else {
12207                                         // copy regs
12208
12209                                         for(i=0;i<size;i++) {
12210                                                 if(i < size-1)
12211                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12212                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12213                                                 else
12214                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12215                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12216                                         }
12217                                 }
12218                                 goto release;
12219                         } 
12220                         // right = ACC
12221                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12222                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12223                         goto release;
12224         } // if (AOP_TYPE(result) != AOP_IMMD)
12225
12226         } // if (AOP_TYPE(result) != AOP_STR)
12227         /* so dptr know contains the address */
12228
12229
12230         /* if bit then unpack */
12231         if (IS_BITFIELD(retype)) 
12232                 genPackBits(retype,result,right,"dptr",GPOINTER);
12233         else {
12234                 size = AOP_SIZE(right);
12235                 offset = 0 ;
12236
12237                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12238
12239                 // set up FSR0 with address of result
12240                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12241                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12242         
12243                 while (size--) {
12244                         if (AOP_TYPE(right) == AOP_LIT) {
12245                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12246                                 if (size) {
12247                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12248                                 } else {
12249                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12250                                 }
12251                         } else { // no literal
12252                                 if(size) {
12253                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12254                                 } else {
12255                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12256                                 }
12257                         }
12258                         offset++;
12259                 }
12260         }
12261
12262         release:
12263         pic16_freeAsmop(right,NULL,ic,TRUE);
12264         pic16_freeAsmop(result,NULL,ic,TRUE);
12265 }
12266 #endif
12267
12268 static void genGenPointerSet (operand *right,
12269                               operand *result, iCode *ic)
12270 {
12271   int size;
12272   sym_link *retype = getSpec(operandType(right));
12273   char fgptrput[32];
12274
12275     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12276
12277     pic16_aopOp(result,ic,FALSE);
12278     pic16_aopOp(right,ic,FALSE);
12279     size = AOP_SIZE(right);
12280
12281     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12282
12283
12284     /* if bit then unpack */
12285     if (IS_BITFIELD(retype)) {
12286 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12287       genPackBits(retype,result,right,"dptr",GPOINTER);
12288       goto release;
12289     }
12290
12291     size = AOP_SIZE(right);
12292
12293     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12294
12295
12296
12297     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12298
12299     /* value of right+0 is placed on stack, which will be retrieved
12300      * by the support function this restoring the stack. The important
12301      * thing is that there is no need to manually restore stack pointer
12302      * here */
12303     pushaop(AOP(right), 0);
12304 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12305     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12306     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12307     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12308     
12309     /* load address to write to in WREG:FSR0H:FSR0L */
12310     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12311                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12312     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12313                                 pic16_popCopyReg(&pic16_pc_prodl)));
12314     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12315     
12316
12317     /* put code here */
12318     switch (size) {
12319       case 1: strcpy(fgptrput, "__gptrput1"); break;
12320       case 2: strcpy(fgptrput, "__gptrput2"); break;
12321       case 3: strcpy(fgptrput, "__gptrput3"); break;
12322       case 4: strcpy(fgptrput, "__gptrput4"); break;
12323       default:
12324         werror(W_POSSBUG2, __FILE__, __LINE__);
12325         abort();
12326     }
12327     
12328     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12329     
12330     {
12331       symbol *sym;
12332                   
12333         sym = newSymbol( fgptrput, 0 );
12334         strcpy(sym->rname, fgptrput);
12335         checkAddSym(&externs, sym);
12336     }
12337
12338 release:
12339     pic16_freeAsmop(right,NULL,ic,TRUE);
12340     pic16_freeAsmop(result,NULL,ic,TRUE);
12341 }
12342
12343 /*-----------------------------------------------------------------*/
12344 /* genPointerSet - stores the value into a pointer location        */
12345 /*-----------------------------------------------------------------*/
12346 static void genPointerSet (iCode *ic)
12347 {    
12348   operand *right, *result ;
12349   sym_link *type, *etype;
12350   int p_type;
12351
12352     FENTRY;
12353
12354     right = IC_RIGHT(ic);
12355     result = IC_RESULT(ic) ;
12356
12357     /* depending on the type of pointer we need to
12358     move it to the correct pointer register */
12359     type = operandType(result);
12360     etype = getSpec(type);
12361     /* if left is of type of pointer then it is simple */
12362     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12363         p_type = DCL_TYPE(type);
12364     }
12365     else {
12366         /* we have to go by the storage class */
12367         p_type = PTR_TYPE(SPEC_OCLS(etype));
12368
12369 /*      if (SPEC_OCLS(etype)->codesp ) { */
12370 /*          p_type = CPOINTER ;  */
12371 /*      } */
12372 /*      else */
12373 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12374 /*              p_type = FPOINTER ; */
12375 /*          else */
12376 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12377 /*                  p_type = PPOINTER ; */
12378 /*              else */
12379 /*                  if (SPEC_OCLS(etype) == idata ) */
12380 /*                      p_type = IPOINTER ; */
12381 /*                  else */
12382 /*                      p_type = POINTER ; */
12383     }
12384
12385     /* now that we have the pointer type we assign
12386     the pointer values */
12387     switch (p_type) {
12388
12389     case POINTER:
12390     case IPOINTER:
12391         genNearPointerSet (right,result,ic);
12392         break;
12393
12394     case PPOINTER:
12395         genPagedPointerSet (right,result,ic);
12396         break;
12397
12398     case FPOINTER:
12399         genFarPointerSet (right,result,ic);
12400         break;
12401
12402     case GPOINTER:
12403         genGenPointerSet (right,result,ic);
12404         break;
12405
12406     default:
12407       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12408               "genPointerSet: illegal pointer type");
12409     }
12410 }
12411
12412 /*-----------------------------------------------------------------*/
12413 /* genIfx - generate code for Ifx statement                        */
12414 /*-----------------------------------------------------------------*/
12415 static void genIfx (iCode *ic, iCode *popIc)
12416 {
12417   operand *cond = IC_COND(ic);
12418   int isbit =0;
12419
12420     FENTRY;
12421
12422     pic16_aopOp(cond,ic,FALSE);
12423
12424     /* get the value into acc */
12425     if (AOP_TYPE(cond) != AOP_CRY)
12426       pic16_toBoolean(cond);
12427     else
12428       isbit = 1;
12429     /* the result is now in the accumulator */
12430     pic16_freeAsmop(cond,NULL,ic,TRUE);
12431
12432     /* if there was something to be popped then do it */
12433     if (popIc)
12434       genIpop(popIc);
12435
12436     /* if the condition is  a bit variable */
12437     if (isbit && IS_ITEMP(cond) && 
12438         SPIL_LOC(cond)) {
12439       genIfxJump(ic,"c");
12440       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12441     } else {
12442       if (isbit && !IS_ITEMP(cond))
12443         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12444         else
12445         genIfxJump(ic,"a");
12446     }
12447     ic->generated = 1;
12448 }
12449
12450 /*-----------------------------------------------------------------*/
12451 /* genAddrOf - generates code for address of                       */
12452 /*-----------------------------------------------------------------*/
12453 static void genAddrOf (iCode *ic)
12454 {
12455   operand *result, *left;
12456   int size;
12457   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12458   pCodeOp *pcop0, *pcop1, *pcop2;
12459
12460     FENTRY;
12461
12462     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12463
12464     sym = OP_SYMBOL( IC_LEFT(ic) );
12465     
12466     if(sym->onStack) {
12467       /* get address of symbol on stack */
12468       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12469 #if 0
12470       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12471                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12472 #endif
12473
12474       // operands on stack are accessible via "FSR2 + index" with index
12475       // starting at 2 for arguments and growing from 0 downwards for
12476       // local variables (index == 0 is not assigned so we add one here)
12477       {
12478         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12479         if (soffs <= 0) {
12480           assert (soffs < 0);
12481           soffs++;
12482         } // if
12483         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12484         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12485         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12486         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12487         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12488         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12489         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12490       }
12491
12492       goto release;
12493     }
12494         
12495 //      if(pic16_debug_verbose) {
12496 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12497 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12498 //      }
12499         
12500     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12501     size = AOP_SIZE(IC_RESULT(ic));
12502
12503
12504     /* Assume that what we want the address of is in data space
12505      * since there is no stack on the PIC, yet! -- VR */
12506   
12507     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12508     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12509     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12510         
12511     if (size == 3) {
12512       pic16_emitpcode(POC_MOVLW, pcop0);
12513       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12514       pic16_emitpcode(POC_MOVLW, pcop1);
12515       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12516       pic16_emitpcode(POC_MOVLW, pcop2);
12517       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12518     } else
12519     if (size == 2) {
12520       pic16_emitpcode(POC_MOVLW, pcop0);
12521       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12522       pic16_emitpcode(POC_MOVLW, pcop1);
12523     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12524     } else {
12525       pic16_emitpcode(POC_MOVLW, pcop0);
12526       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12527     }
12528
12529     pic16_freeAsmop(left, NULL, ic, FALSE);
12530 release:
12531     pic16_freeAsmop(result,NULL,ic,TRUE);
12532 }
12533
12534
12535 #if 0
12536 /*-----------------------------------------------------------------*/
12537 /* genFarFarAssign - assignment when both are in far space         */
12538 /*-----------------------------------------------------------------*/
12539 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12540 {
12541     int size = AOP_SIZE(right);
12542     int offset = 0;
12543     char *l ;
12544     /* first push the right side on to the stack */
12545     while (size--) {
12546         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12547         MOVA(l);
12548         pic16_emitcode ("push","acc");
12549     }
12550     
12551     pic16_freeAsmop(right,NULL,ic,FALSE);
12552     /* now assign DPTR to result */
12553     pic16_aopOp(result,ic,FALSE);
12554     size = AOP_SIZE(result);
12555     while (size--) {
12556         pic16_emitcode ("pop","acc");
12557         pic16_aopPut(AOP(result),"a",--offset);
12558     }
12559     pic16_freeAsmop(result,NULL,ic,FALSE);
12560         
12561 }
12562 #endif
12563
12564 /*-----------------------------------------------------------------*/
12565 /* genAssign - generate code for assignment                        */
12566 /*-----------------------------------------------------------------*/
12567 static void genAssign (iCode *ic)
12568 {
12569   operand *result, *right;
12570   int size, offset,know_W;
12571   unsigned long lit = 0L;
12572
12573   result = IC_RESULT(ic);
12574   right  = IC_RIGHT(ic) ;
12575
12576   FENTRY;
12577   
12578   /* if they are the same */
12579   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12580     return ;
12581
12582   /* reversed order operands are aopOp'ed so that result operand
12583    * is effective in case right is a stack symbol. This maneauver
12584    * allows to use the _G.resDirect flag later */
12585   pic16_aopOp(result,ic,TRUE);
12586   pic16_aopOp(right,ic,FALSE);
12587
12588   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12589
12590   /* if they are the same registers */
12591   if (pic16_sameRegs(AOP(right),AOP(result)))
12592     goto release;
12593
12594   /* if the result is a bit */
12595   if (AOP_TYPE(result) == AOP_CRY) {
12596     /* if the right size is a literal then
12597        we know what the value is */
12598     if (AOP_TYPE(right) == AOP_LIT) {
12599           
12600       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12601                   pic16_popGet(AOP(result),0));
12602
12603       if (((int) operandLitValue(right))) 
12604         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12605                        AOP(result)->aopu.aop_dir,
12606                        AOP(result)->aopu.aop_dir);
12607       else
12608         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12609                        AOP(result)->aopu.aop_dir,
12610                        AOP(result)->aopu.aop_dir);
12611       goto release;
12612     }
12613
12614     /* the right is also a bit variable */
12615     if (AOP_TYPE(right) == AOP_CRY) {
12616       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12617       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12618       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12619
12620       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12621                      AOP(result)->aopu.aop_dir,
12622                      AOP(result)->aopu.aop_dir);
12623       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12624                      AOP(right)->aopu.aop_dir,
12625                      AOP(right)->aopu.aop_dir);
12626       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12627                      AOP(result)->aopu.aop_dir,
12628                      AOP(result)->aopu.aop_dir);
12629       goto release ;
12630     }
12631
12632     /* we need to or */
12633     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12634     pic16_toBoolean(right);
12635     emitSKPZ;
12636     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12637     //pic16_aopPut(AOP(result),"a",0);
12638     goto release ;
12639   }
12640
12641   /* bit variables done */
12642   /* general case */
12643   size = AOP_SIZE(result);
12644   offset = 0 ;
12645
12646   if(AOP_TYPE(right) == AOP_LIT) {
12647         if(!IS_FLOAT(operandType( right )))
12648                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12649         else {
12650            union {
12651               unsigned long lit_int;
12652               float lit_float;
12653             } info;
12654         
12655                 /* take care if literal is a float */
12656                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12657                 lit = info.lit_int;
12658         }
12659   }
12660
12661 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12662 //                      sizeof(unsigned long int), sizeof(float));
12663
12664
12665   if (AOP_TYPE(right) == AOP_REG) {
12666     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12667     while (size--) {
12668       
12669       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12670     } // while
12671     goto release;
12672   }
12673
12674   if(AOP_TYPE(right) != AOP_LIT
12675         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12676         && !IS_FUNC(OP_SYM_TYPE(right))
12677         ) {
12678         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12679         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12680
12681         // set up table pointer
12682         if(is_LitOp(right)) {
12683 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12684                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12685                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12686                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12687                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12688                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12689                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12690         } else {
12691 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12692                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12693                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12694                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12695                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12696                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12697                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12698         }
12699
12700         size = min(AOP_SIZE(right), AOP_SIZE(result));
12701         while(size--) {
12702                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12703                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12704                         pic16_popGet(AOP(result),offset)));
12705                 offset++;
12706         }
12707
12708         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12709                 size = AOP_SIZE(result) - AOP_SIZE(right);
12710                 while(size--) {
12711                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12712                         offset++;
12713                 }
12714         }
12715         goto release;
12716   }
12717
12718
12719
12720 #if 0
12721 /* VR - What is this?! */
12722   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12723     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12724     if(aopIdx(AOP(result),0) == 4) {
12725
12726       /* this is a workaround to save value of right into wreg too,
12727        * value of wreg is going to be used later */
12728       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12729       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12730       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12731       goto release;
12732     } else
12733 //      assert(0);
12734       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12735   }
12736 #endif
12737
12738   know_W=-1;
12739   while (size--) {
12740   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12741     if(AOP_TYPE(right) == AOP_LIT) {
12742       if(lit&0xff) {
12743         if(know_W != (lit&0xff))
12744           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12745         know_W = lit&0xff;
12746         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12747       } else
12748         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12749
12750       lit >>= 8;
12751
12752     } else if (AOP_TYPE(right) == AOP_CRY) {
12753       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12754       if(offset == 0) {
12755         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12756         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12757         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12758       }
12759     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12760         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12761         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12762     } else {
12763       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12764
12765       if(!_G.resDirect)         /* use this aopForSym feature */
12766         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12767     }
12768             
12769     offset++;
12770   }
12771   
12772  release:
12773   pic16_freeAsmop (right,NULL,ic,FALSE);
12774   pic16_freeAsmop (result,NULL,ic,TRUE);
12775 }   
12776
12777 /*-----------------------------------------------------------------*/
12778 /* genJumpTab - generates code for jump table                       */
12779 /*-----------------------------------------------------------------*/
12780 static void genJumpTab (iCode *ic)
12781 {
12782   symbol *jtab;
12783   char *l;
12784   pCodeOp *jt_offs;
12785   pCodeOp *jt_offs_hi;
12786   pCodeOp *jt_label;
12787
12788     FENTRY;
12789
12790     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12791     /* get the condition into accumulator */
12792     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12793     MOVA(l);
12794     /* multiply by three */
12795     pic16_emitcode("add","a,acc");
12796     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12797
12798     jtab = newiTempLabel(NULL);
12799     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12800     pic16_emitcode("jmp","@a+dptr");
12801     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12802
12803 #if 0
12804     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12805     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12806     emitSKPNC;
12807     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12808     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12809     pic16_emitpLabel(jtab->key);
12810
12811 #else
12812
12813     jt_offs = pic16_popGetTempReg(0);
12814     jt_offs_hi = pic16_popGetTempReg(1);
12815     jt_label = pic16_popGetLabel (jtab->key);
12816     //fprintf (stderr, "Creating jump table...\n");
12817
12818     // calculate offset into jump table (idx * sizeof (GOTO))
12819     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12820     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12821     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12822     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12823     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12824     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12825     pic16_emitpcode(POC_MOVWF , jt_offs);
12826
12827     // prepare PCLATx (set to first entry in jump table)
12828     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12829     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12830     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12831     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12832     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12833
12834     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12835     pic16_emitpcode(POC_ADDWF , jt_offs);
12836     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12837     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12838     emitSKPNC;
12839     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12840
12841     // release temporaries and prepare jump into table (new PCL --> WREG)
12842     pic16_emitpcode(POC_MOVFW , jt_offs);
12843     pic16_popReleaseTempReg (jt_offs_hi, 1);
12844     pic16_popReleaseTempReg (jt_offs, 0);
12845
12846     // jump into the table
12847     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12848
12849     pic16_emitpLabelFORCE(jtab->key);
12850
12851 #endif
12852     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12853
12854     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12855     /* now generate the jump labels */
12856     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12857          jtab = setNextItem(IC_JTLABELS(ic))) {
12858 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12859         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12860         
12861     }
12862     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12863
12864 }
12865
12866 /*-----------------------------------------------------------------*/
12867 /* genMixedOperation - gen code for operators between mixed types  */
12868 /*-----------------------------------------------------------------*/
12869 /*
12870   TSD - Written for the PIC port - but this unfortunately is buggy.
12871   This routine is good in that it is able to efficiently promote 
12872   types to different (larger) sizes. Unfortunately, the temporary
12873   variables that are optimized out by this routine are sometimes
12874   used in other places. So until I know how to really parse the 
12875   iCode tree, I'm going to not be using this routine :(.
12876 */
12877 static int genMixedOperation (iCode *ic)
12878 {
12879 #if 0
12880   operand *result = IC_RESULT(ic);
12881   sym_link *ctype = operandType(IC_LEFT(ic));
12882   operand *right = IC_RIGHT(ic);
12883   int ret = 0;
12884   int big,small;
12885   int offset;
12886
12887   iCode *nextic;
12888   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12889
12890   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12891
12892   nextic = ic->next;
12893   if(!nextic)
12894     return 0;
12895
12896   nextright = IC_RIGHT(nextic);
12897   nextleft  = IC_LEFT(nextic);
12898   nextresult = IC_RESULT(nextic);
12899
12900   pic16_aopOp(right,ic,FALSE);
12901   pic16_aopOp(result,ic,FALSE);
12902   pic16_aopOp(nextright,  nextic, FALSE);
12903   pic16_aopOp(nextleft,   nextic, FALSE);
12904   pic16_aopOp(nextresult, nextic, FALSE);
12905
12906   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12907
12908     operand *t = right;
12909     right = nextright;
12910     nextright = t; 
12911
12912     pic16_emitcode(";remove right +","");
12913
12914   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12915 /*
12916     operand *t = right;
12917     right = nextleft;
12918     nextleft = t; 
12919 */
12920     pic16_emitcode(";remove left +","");
12921   } else
12922     return 0;
12923
12924   big = AOP_SIZE(nextleft);
12925   small = AOP_SIZE(nextright);
12926
12927   switch(nextic->op) {
12928
12929   case '+':
12930     pic16_emitcode(";optimize a +","");
12931     /* if unsigned or not an integral type */
12932     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12933       pic16_emitcode(";add a bit to something","");
12934     } else {
12935
12936       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12937
12938       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12939         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12940         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12941       } else
12942         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12943
12944       offset = 0;
12945       while(--big) {
12946
12947         offset++;
12948
12949         if(--small) {
12950           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12951             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12952             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12953           }
12954
12955           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12956           emitSKPNC;
12957           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12958                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12959                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12960           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12961           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12962
12963         } else {
12964           pic16_emitcode("rlf","known_zero,w");
12965
12966           /*
12967             if right is signed
12968               btfsc  right,7
12969                addlw ff
12970           */
12971           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12972             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12973             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12974           } else {
12975             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12976           }
12977         }
12978       }
12979       ret = 1;
12980     }
12981   }
12982   ret = 1;
12983
12984 release:
12985   pic16_freeAsmop(right,NULL,ic,TRUE);
12986   pic16_freeAsmop(result,NULL,ic,TRUE);
12987   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12988   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12989   if(ret)
12990     nextic->generated = 1;
12991
12992   return ret;
12993 #else
12994   return 0;
12995 #endif
12996 }
12997 /*-----------------------------------------------------------------*/
12998 /* genCast - gen code for casting                                  */
12999 /*-----------------------------------------------------------------*/
13000 static void genCast (iCode *ic)
13001 {
13002   operand *result = IC_RESULT(ic);
13003   sym_link *ctype = operandType(IC_LEFT(ic));
13004   sym_link *rtype = operandType(IC_RIGHT(ic));
13005   sym_link *restype = operandType(IC_RESULT(ic));
13006   operand *right = IC_RIGHT(ic);
13007   int size, offset ;
13008
13009
13010     FENTRY;
13011
13012         /* if they are equivalent then do nothing */
13013 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13014 //              return ;
13015
13016         pic16_aopOp(right,ic,FALSE) ;
13017         pic16_aopOp(result,ic,FALSE);
13018
13019         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13020
13021
13022         /* if the result is a bit */
13023         if (AOP_TYPE(result) == AOP_CRY) {
13024         
13025                 /* if the right size is a literal then
13026                  * we know what the value is */
13027                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13028
13029                 if (AOP_TYPE(right) == AOP_LIT) {
13030                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13031                                 pic16_popGet(AOP(result),0));
13032
13033                         if (((int) operandLitValue(right))) 
13034                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13035                                         AOP(result)->aopu.aop_dir,
13036                                         AOP(result)->aopu.aop_dir);
13037                         else
13038                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13039                                         AOP(result)->aopu.aop_dir,
13040                                         AOP(result)->aopu.aop_dir);
13041                         goto release;
13042                 }
13043
13044                 /* the right is also a bit variable */
13045                 if (AOP_TYPE(right) == AOP_CRY) {
13046                         emitCLRC;
13047                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13048
13049                         pic16_emitcode("clrc","");
13050                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13051                                 AOP(right)->aopu.aop_dir,
13052                                 AOP(right)->aopu.aop_dir);
13053                         pic16_aopPut(AOP(result),"c",0);
13054                         goto release ;
13055                 }
13056
13057                 /* we need to or */
13058                 if (AOP_TYPE(right) == AOP_REG) {
13059                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13060                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13061                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13062                 }
13063                 pic16_toBoolean(right);
13064                 pic16_aopPut(AOP(result),"a",0);
13065                 goto release ;
13066         }
13067
13068         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13069           int offset = 1;
13070
13071                 size = AOP_SIZE(result);
13072
13073                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13074
13075                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13076                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13077                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13078
13079                 while (size--)
13080                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13081
13082                 goto release;
13083         }
13084
13085         if(IS_BITFIELD(getSpec(restype))
13086           && IS_BITFIELD(getSpec(rtype))) {
13087           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13088         }
13089
13090         /* if they are the same size : or less */
13091         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13092
13093                 /* if they are in the same place */
13094                 if (pic16_sameRegs(AOP(right),AOP(result)))
13095                         goto release;
13096
13097                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13098 #if 0
13099                 if (IS_PTR_CONST(rtype))
13100 #else
13101                 if (IS_CODEPTR(rtype))
13102 #endif
13103                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13104
13105 #if 0
13106                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13107 #else
13108                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13109 #endif
13110                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13111
13112 #if 0
13113                 if(AOP_TYPE(right) == AOP_IMMD) {
13114                   pCodeOp *pcop0, *pcop1, *pcop2;
13115                   symbol *sym = OP_SYMBOL( right );
13116
13117                         size = AOP_SIZE(result);
13118                         /* low */
13119                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13120                         /* high */
13121                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13122                         /* upper */
13123                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13124         
13125                         if (size == 3) {
13126                                 pic16_emitpcode(POC_MOVLW, pcop0);
13127                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13128                                 pic16_emitpcode(POC_MOVLW, pcop1);
13129                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13130                                 pic16_emitpcode(POC_MOVLW, pcop2);
13131                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13132                         } else
13133                         if (size == 2) {
13134                                 pic16_emitpcode(POC_MOVLW, pcop0);
13135                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13136                                 pic16_emitpcode(POC_MOVLW, pcop1);
13137                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13138                         } else {
13139                                 pic16_emitpcode(POC_MOVLW, pcop0);
13140                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13141                         }
13142                 } else
13143 #endif
13144                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13145                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13146                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13147                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13148                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13149                         if(AOP_SIZE(result) <2)
13150                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13151                 } else {
13152                         /* if they in different places then copy */
13153                         size = AOP_SIZE(result);
13154                         offset = 0 ;
13155                         while (size--) {
13156                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13157                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13158                                 offset++;
13159                         }
13160                 }
13161                 goto release;
13162         }
13163
13164         /* if the result is of type pointer */
13165         if (IS_PTR(ctype)) {
13166           int p_type;
13167           sym_link *type = operandType(right);
13168           sym_link *etype = getSpec(type);
13169
13170                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13171
13172                 /* pointer to generic pointer */
13173                 if (IS_GENPTR(ctype)) {
13174                   char *l = zero;
13175             
13176                         if (IS_PTR(type)) 
13177                                 p_type = DCL_TYPE(type);
13178                         else {
13179                 /* we have to go by the storage class */
13180                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13181
13182 /*              if (SPEC_OCLS(etype)->codesp )  */
13183 /*                  p_type = CPOINTER ;  */
13184 /*              else */
13185 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13186 /*                      p_type = FPOINTER ; */
13187 /*                  else */
13188 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13189 /*                          p_type = PPOINTER; */
13190 /*                      else */
13191 /*                          if (SPEC_OCLS(etype) == idata ) */
13192 /*                              p_type = IPOINTER ; */
13193 /*                          else */
13194 /*                              p_type = POINTER ; */
13195             }
13196                 
13197             /* the first two bytes are known */
13198       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13199             size = GPTRSIZE - 1; 
13200             offset = 0 ;
13201             while (size--) {
13202               if(offset < AOP_SIZE(right)) {
13203                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13204                 mov2f(AOP(result), AOP(right), offset);
13205 /*
13206                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13207                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13208                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13209                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13210                 } else { 
13211                   
13212                   pic16_aopPut(AOP(result),
13213                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13214                          offset);
13215                 }
13216 */
13217               } else 
13218                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13219               offset++;
13220             }
13221             /* the last byte depending on type */
13222             switch (p_type) {
13223             case IPOINTER:
13224             case POINTER:
13225                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13226                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13227 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13228                 break;
13229
13230             case CPOINTER:
13231                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13232                 break;
13233
13234             case FPOINTER:
13235               pic16_emitcode(";BUG!? ","%d",__LINE__);
13236                 l = one;
13237                 break;
13238             case PPOINTER:
13239               pic16_emitcode(";BUG!? ","%d",__LINE__);
13240                 l = "#0x03";
13241                 break;
13242
13243             case GPOINTER:
13244               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13245               break;
13246               
13247             default:
13248                 /* this should never happen */
13249                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13250                        "got unknown pointer type");
13251                 exit(1);
13252             }
13253             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13254             goto release ;
13255         }
13256         
13257         /* just copy the pointers */
13258         size = AOP_SIZE(result);
13259         offset = 0 ;
13260         while (size--) {
13261             pic16_aopPut(AOP(result),
13262                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13263                    offset);
13264             offset++;
13265         }
13266         goto release ;
13267     }
13268     
13269
13270
13271     /* so we now know that the size of destination is greater
13272     than the size of the source.
13273     Now, if the next iCode is an operator then we might be
13274     able to optimize the operation without performing a cast.
13275     */
13276     if(genMixedOperation(ic))
13277       goto release;
13278
13279     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13280     
13281     /* we move to result for the size of source */
13282     size = AOP_SIZE(right);
13283     offset = 0 ;
13284     while (size--) {
13285       mov2f(AOP(result), AOP(right), offset);
13286       offset++;
13287     }
13288
13289     /* now depending on the sign of the destination */
13290     size = AOP_SIZE(result) - AOP_SIZE(right);
13291     /* if unsigned or not an integral type */
13292     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13293       while (size--)
13294         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13295     } else {
13296       /* we need to extend the sign :( */
13297
13298       if(size == 1) {
13299         /* Save one instruction of casting char to int */
13300         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13301         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13302         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13303       } else {
13304         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13305
13306         if(offset)
13307           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13308         else
13309           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13310         
13311         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13312
13313         while (size--)
13314           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13315       }
13316     }
13317
13318 release:
13319     pic16_freeAsmop(right,NULL,ic,TRUE);
13320     pic16_freeAsmop(result,NULL,ic,TRUE);
13321
13322 }
13323
13324 /*-----------------------------------------------------------------*/
13325 /* genDjnz - generate decrement & jump if not zero instrucion      */
13326 /*-----------------------------------------------------------------*/
13327 static int genDjnz (iCode *ic, iCode *ifx)
13328 {
13329     symbol *lbl, *lbl1;
13330     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13331
13332     if (!ifx)
13333         return 0;
13334     
13335     /* if the if condition has a false label
13336        then we cannot save */
13337     if (IC_FALSE(ifx))
13338         return 0;
13339
13340     /* if the minus is not of the form 
13341        a = a - 1 */
13342     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13343         !IS_OP_LITERAL(IC_RIGHT(ic)))
13344         return 0;
13345
13346     if (operandLitValue(IC_RIGHT(ic)) != 1)
13347         return 0;
13348
13349     /* if the size of this greater than one then no
13350        saving */
13351     if (getSize(operandType(IC_RESULT(ic))) > 1)
13352         return 0;
13353
13354     /* otherwise we can save BIG */
13355     lbl = newiTempLabel(NULL);
13356     lbl1= newiTempLabel(NULL);
13357
13358     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13359     
13360     if (IS_AOP_PREG(IC_RESULT(ic))) {
13361         pic16_emitcode("dec","%s",
13362                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13363         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13364         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13365     } else {    
13366
13367
13368       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13369       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13370
13371       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13372       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13373
13374     }
13375     
13376     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13377     ifx->generated = 1;
13378     return 1;
13379 }
13380
13381 /*-----------------------------------------------------------------*/
13382 /* genReceive - generate code for a receive iCode                  */
13383 /*-----------------------------------------------------------------*/
13384 static void genReceive (iCode *ic)
13385 {    
13386
13387   FENTRY;
13388
13389 #if 0
13390   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13391         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13392 #endif
13393 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13394
13395   if (isOperandInFarSpace(IC_RESULT(ic))
13396       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13397           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13398
13399     int size = getSize(operandType(IC_RESULT(ic)));
13400     int offset =  pic16_fReturnSizePic - size;
13401
13402       assert( 0 );
13403       while (size--) {
13404         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13405                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13406                       offset++;
13407         }
13408
13409       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13410
13411       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13412       size = AOP_SIZE(IC_RESULT(ic));
13413       offset = 0;
13414       while (size--) {
13415         pic16_emitcode ("pop","acc");
13416         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13417       }
13418   } else {
13419     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13420     _G.accInUse++;
13421     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13422     _G.accInUse--;
13423
13424     /* set pseudo stack pointer to where it should be - dw*/
13425     GpsuedoStkPtr = ic->parmBytes;
13426
13427     /* setting GpsuedoStkPtr has side effects here: */
13428     assignResultValue(IC_RESULT(ic), 0);
13429   }
13430
13431   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13432 }
13433
13434 /*-----------------------------------------------------------------*/
13435 /* genDummyRead - generate code for dummy read of volatiles        */
13436 /*-----------------------------------------------------------------*/
13437 static void
13438 genDummyRead (iCode * ic)
13439 {
13440   pic16_emitcode ("; genDummyRead","");
13441   pic16_emitcode ("; not implemented","");
13442
13443   ic = ic;
13444 }
13445
13446 /*-----------------------------------------------------------------*/
13447 /* genpic16Code - generate code for pic16 based controllers        */
13448 /*-----------------------------------------------------------------*/
13449 /*
13450  * At this point, ralloc.c has gone through the iCode and attempted
13451  * to optimize in a way suitable for a PIC. Now we've got to generate
13452  * PIC instructions that correspond to the iCode.
13453  *
13454  * Once the instructions are generated, we'll pass through both the
13455  * peep hole optimizer and the pCode optimizer.
13456  *-----------------------------------------------------------------*/
13457
13458 void genpic16Code (iCode *lic)
13459 {
13460   iCode *ic;
13461   int cln = 0;
13462
13463     lineHead = lineCurr = NULL;
13464
13465     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13466     pic16_addpBlock(pb);
13467
13468 #if 0
13469     /* if debug information required */
13470     if (options.debug && currFunc) {
13471       if (currFunc) {
13472         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13473       }
13474     }
13475 #endif
13476
13477     for (ic = lic ; ic ; ic = ic->next ) {
13478
13479       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13480       if ( cln != ic->lineno ) {
13481         if ( options.debug ) {
13482           debugFile->writeCLine (ic);
13483         }
13484         
13485         if(!options.noCcodeInAsm) {
13486           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13487               printCLine(ic->filename, ic->lineno)));
13488         }
13489
13490         cln = ic->lineno ;
13491       }
13492         
13493       if(options.iCodeInAsm) {
13494         char *l;
13495
13496           /* insert here code to print iCode as comment */
13497           l = Safe_strdup(printILine(ic));
13498           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13499       }
13500         
13501       /* if the result is marked as
13502        * spilt and rematerializable or code for
13503        * this has already been generated then
13504        * do nothing */
13505       if (resultRemat(ic) || ic->generated ) 
13506         continue ;
13507         
13508       /* depending on the operation */
13509       switch (ic->op) {
13510         case '!' :
13511           pic16_genNot(ic);
13512           break;
13513             
13514         case '~' :
13515           pic16_genCpl(ic);
13516           break;
13517             
13518         case UNARYMINUS:
13519           genUminus (ic);
13520           break;
13521             
13522         case IPUSH:
13523           genIpush (ic);
13524           break;
13525             
13526         case IPOP:
13527           /* IPOP happens only when trying to restore a 
13528            * spilt live range, if there is an ifx statement
13529            * following this pop then the if statement might
13530            * be using some of the registers being popped which
13531            * would destroy the contents of the register so
13532            * we need to check for this condition and handle it */
13533            if (ic->next
13534              && ic->next->op == IFX
13535              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13536                genIfx (ic->next,ic);
13537           else
13538             genIpop (ic);
13539           break; 
13540             
13541         case CALL:
13542           genCall (ic);
13543           break;
13544             
13545         case PCALL:
13546           genPcall (ic);
13547           break;
13548             
13549         case FUNCTION:
13550           genFunction (ic);
13551           break;
13552             
13553         case ENDFUNCTION:
13554           genEndFunction (ic);
13555           break;
13556             
13557         case RETURN:
13558           genRet (ic);
13559           break;
13560             
13561         case LABEL:
13562           genLabel (ic);
13563           break;
13564             
13565         case GOTO:
13566           genGoto (ic);
13567           break;
13568             
13569         case '+' :
13570           pic16_genPlus (ic) ;
13571           break;
13572             
13573         case '-' :
13574           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13575             pic16_genMinus (ic);
13576           break;
13577
13578         case '*' :
13579           genMult (ic);
13580           break;
13581             
13582         case '/' :
13583           genDiv (ic) ;
13584           break;
13585             
13586         case '%' :
13587           genMod (ic);
13588           break;
13589             
13590         case '>' :
13591           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13592           break;
13593             
13594         case '<' :
13595           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13596           break;
13597             
13598         case LE_OP:
13599         case GE_OP:
13600         case NE_OP:
13601           /* note these two are xlated by algebraic equivalence
13602            * during parsing SDCC.y */
13603           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13604             "got '>=' or '<=' shouldn't have come here");
13605           break;
13606
13607         case EQ_OP:
13608           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13609           break;            
13610             
13611         case AND_OP:
13612           genAndOp (ic);
13613           break;
13614             
13615         case OR_OP:
13616           genOrOp (ic);
13617           break;
13618             
13619         case '^' :
13620           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13621           break;
13622             
13623         case '|' :
13624           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13625           break;
13626             
13627         case BITWISEAND:
13628           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13629           break;
13630             
13631         case INLINEASM:
13632           genInline (ic);
13633           break;
13634             
13635         case RRC:
13636           genRRC (ic);
13637           break;
13638             
13639         case RLC:
13640           genRLC (ic);
13641           break;
13642             
13643         case GETHBIT:
13644           genGetHbit (ic);
13645           break;
13646             
13647         case LEFT_OP:
13648           genLeftShift (ic);
13649           break;
13650             
13651         case RIGHT_OP:
13652           genRightShift (ic);
13653           break;
13654             
13655         case GET_VALUE_AT_ADDRESS:
13656           genPointerGet(ic);
13657           break;
13658             
13659         case '=' :
13660           if (POINTER_SET(ic))
13661             genPointerSet(ic);
13662           else
13663             genAssign(ic);
13664           break;
13665             
13666         case IFX:
13667           genIfx (ic,NULL);
13668           break;
13669             
13670         case ADDRESS_OF:
13671           genAddrOf (ic);
13672           break;
13673             
13674         case JUMPTABLE:
13675           genJumpTab (ic);
13676           break;
13677             
13678         case CAST:
13679           genCast (ic);
13680           break;
13681             
13682         case RECEIVE:
13683           genReceive(ic);
13684           break;
13685             
13686         case SEND:
13687           addSet(&_G.sendSet,ic);
13688           break;
13689
13690         case DUMMY_READ_VOLATILE:
13691           genDummyRead (ic);
13692           break;
13693
13694         default :
13695           ic = ic;
13696       }
13697     }
13698
13699
13700     /* now we are ready to call the
13701        peep hole optimizer */
13702     if (!options.nopeep)
13703       peepHole (&lineHead);
13704
13705     /* now do the actual printing */
13706     printLine (lineHead, codeOutFile);
13707
13708 #ifdef PCODE_DEBUG
13709     DFPRINTF((stderr,"printing pBlock\n\n"));
13710     pic16_printpBlock(stdout,pb);
13711 #endif
13712
13713     return;
13714 }
13715