* src/pic16/gen.c (pic16_derefPtr): NEW, single place
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
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 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
141
142 static char *accUse[] = {"WREG"};
143
144 //static short rbank = -1;
145
146 static struct {
147     short r0Pushed;
148     short r1Pushed;
149     short fsr0Pushed;
150     short accInUse;
151     short inLine;
152     short debugLine;
153     short nRegsSaved;
154     short ipushRegs;
155     set *sendSet;
156     set *stackRegSet;
157     int usefastretfie;
158     bitVect *fregsUsed;                 /* registers used in function */
159     bitVect *sregsAlloc;
160     set *sregsAllocSet;                 /* registers used to store stack variables */
161     int stack_lat;                      /* stack offset latency */
162     int resDirect;
163     int useWreg;                        /* flag when WREG is used to pass function parameter */
164 } _G;
165
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
170
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
173
174 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
178
179 static  pBlock *pb;
180
181 /*-----------------------------------------------------------------*/
182 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
183 /*                 exponent of 2 is returned, otherwise -1 is      */
184 /*                 returned.                                       */
185 /* note that this is similar to the function `powof2' in SDCCsymt  */
186 /* if(n == 2^y)                                                    */
187 /*   return y;                                                     */
188 /* return -1;                                                      */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
191 {
192   if(num) {
193     if( (num & (num-1)) == 0) {
194       int nshifts = -1;
195       while(num) {
196         num>>=1;
197         nshifts++;
198       }
199       return nshifts;
200     }
201   }
202
203   return -1;
204 }
205
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 {
208   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209                        line_no,
210                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
213                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
215                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216                        ((result) ? AOP_SIZE(result) : 0));
217 }
218
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
220 {
221
222   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
230
231 }
232
233 void pic16_emitpcomment (char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     va_start(ap,fmt);   
240
241     lb[0] = ';';
242     vsprintf(lb+1,fmt,ap);
243
244     while (isspace(*lbp)) lbp++;
245
246     if (lbp && *lbp) 
247         lineCurr = (lineCurr ?
248                     connectLine(lineCurr,newLineNode(lb)) :
249                     (lineHead = newLineNode(lb)));
250     lineCurr->isInline = _G.inLine;
251     lineCurr->isDebug  = _G.debugLine;
252
253     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
254     va_end(ap);
255
256 //      fprintf(stderr, "%s\n", lb);
257 }
258
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
260 {
261     va_list ap;
262     char lb[INITIAL_INLINEASM];  
263     char *lbp = lb;
264
265     if(!pic16_debug_verbose)
266       return;
267
268     va_start(ap,fmt);   
269
270     if (inst && *inst) {
271         if (fmt && *fmt)
272             sprintf(lb,"%s\t",inst);
273         else
274             sprintf(lb,"%s",inst);
275         vsprintf(lb+(strlen(lb)),fmt,ap);
276     }  else
277         vsprintf(lb,fmt,ap);
278
279     while (isspace(*lbp)) lbp++;
280
281     if (lbp && *lbp) 
282         lineCurr = (lineCurr ?
283                     connectLine(lineCurr,newLineNode(lb)) :
284                     (lineHead = newLineNode(lb)));
285     lineCurr->isInline = _G.inLine;
286     lineCurr->isDebug  = _G.debugLine;
287
288     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
289     va_end(ap);
290
291 //      fprintf(stderr, "%s\n", lb);
292 }
293
294
295
296 void pic16_emitpLabel(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpLabelFORCE(int key)
302 {
303   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
304 }
305
306 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
307  * NEVER call pic16_emitpcode_real directly, please... */
308 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
309 {
310
311   if(pcop)
312     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
313   else
314     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
315 }
316
317 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
318 {
319   if(pcop)
320     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
321   else
322     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
323 }
324   
325 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
326 {
327
328   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
329
330 }
331
332
333 #if 1
334 #define pic16_emitcode  DEBUGpic16_emitcode
335 #else
336 /*-----------------------------------------------------------------*/
337 /* pic16_emitcode - writes the code into a file : for now it is simple    */
338 /*-----------------------------------------------------------------*/
339 void pic16_emitcode (char *inst,char *fmt, ...)
340 {
341     va_list ap;
342     char lb[INITIAL_INLINEASM];  
343     char *lbp = lb;
344
345     va_start(ap,fmt);   
346
347     if (inst && *inst) {
348         if (fmt && *fmt)
349             sprintf(lb,"%s\t",inst);
350         else
351             sprintf(lb,"%s",inst);
352         vsprintf(lb+(strlen(lb)),fmt,ap);
353     }  else
354         vsprintf(lb,fmt,ap);
355
356     while (isspace(*lbp)) lbp++;
357
358     if (lbp && *lbp) 
359         lineCurr = (lineCurr ?
360                     connectLine(lineCurr,newLineNode(lb)) :
361                     (lineHead = newLineNode(lb)));
362     lineCurr->isInline = _G.inLine;
363     lineCurr->isDebug  = _G.debugLine;
364
365 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
366
367 //    if(pic16_debug_verbose)
368 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
369
370     va_end(ap);
371 }
372 #endif
373
374
375 /*-----------------------------------------------------------------*/
376 /* pic16_emitDebuggerSymbol - associate the current code location  */
377 /*   with a debugger symbol                                        */
378 /*-----------------------------------------------------------------*/
379 void
380 pic16_emitDebuggerSymbol (char * debugSym)
381 {
382   _G.debugLine = 1;
383   pic16_emitcode (";", "%s ==.", debugSym);
384   _G.debugLine = 0;
385 }
386
387
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
390 /*-----------------------------------------------------------------*/
391 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
392 {
393 //    bool r0iu = FALSE , r1iu = FALSE;
394 //    bool r0ou = FALSE , r1ou = FALSE;
395     bool fsr0iu = FALSE, fsr0ou;
396     bool fsr2iu = FALSE, fsr2ou;
397     
398     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
399
400     
401     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
402     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
403     
404     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
405     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
406
407     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
408         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
409         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
410     }
411
412     if(!fsr0iu && !fsr0ou) {
413         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
414         (*aopp)->type = AOP_FSR0;
415
416         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
417         
418       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
419     }
420
421 #if 0
422     /* no usage of FSR2 */
423     if(!fsr2iu && !fsr2ou) {
424         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
425         (*aopp)->type = AOP_FSR2;
426
427       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
428     }
429 #endif
430         
431     /* now we know they both have usage */
432     /* if fsr0 not used in this instruction */
433     if (!fsr0iu) {
434         if (!_G.fsr0Pushed) {
435                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
436                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
437                 _G.fsr0Pushed++;
438         }
439
440         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
441         (*aopp)->type = AOP_FSR0;
442
443 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
444
445       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
446     }
447         
448
449     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
450     assert( 0 );
451
452     return NULL;
453 #if 0
454     /* the logic: if r0 & r1 used in the instruction
455     then we are in trouble otherwise */
456
457     /* first check if r0 & r1 are used by this
458     instruction, in which case we are in trouble */
459     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
460         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
461     {
462         goto endOfWorld;      
463     }
464
465     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
466     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
467
468     /* if no usage of r0 then return it */
469     if (!r0iu && !r0ou) {
470         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
471         (*aopp)->type = AOP_R0; 
472         
473         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
474     }
475
476     /* if no usage of r1 then return it */
477     if (!r1iu && !r1ou) {
478         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
479         (*aopp)->type = AOP_R1;
480
481         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
482     }    
483
484     /* now we know they both have usage */
485     /* if r0 not used in this instruction */
486     if (!r0iu) {
487         /* push it if not already pushed */
488         if (!_G.r0Pushed) {
489           //pic16_emitcode ("push","%s",
490           //          pic16_regWithIdx(R0_IDX)->dname);
491             _G.r0Pushed++ ;
492         }
493         
494         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
495         (*aopp)->type = AOP_R0;
496
497         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
498     }
499
500     /* if r1 not used then */
501
502     if (!r1iu) {
503         /* push it if not already pushed */
504         if (!_G.r1Pushed) {
505           //pic16_emitcode ("push","%s",
506           //          pic16_regWithIdx(R1_IDX)->dname);
507             _G.r1Pushed++ ;
508         }
509         
510         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
511         (*aopp)->type = AOP_R1;
512         return pic16_regWithIdx(R1_IDX);
513     }
514
515 endOfWorld :
516     /* I said end of world but not quite end of world yet */
517     /* if this is a result then we can push it on the stack*/
518     if (result) {
519         (*aopp)->type = AOP_STK;    
520         return NULL;
521     }
522
523     /* other wise this is true end of the world */
524     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
525            "getFreePtr should never reach here");
526     exit(0);
527 #endif
528 }
529
530 /*-----------------------------------------------------------------*/
531 /* newAsmop - creates a new asmOp                                  */
532 /*-----------------------------------------------------------------*/
533 static asmop *newAsmop (short type)
534 {
535     asmop *aop;
536
537     aop = Safe_calloc(1,sizeof(asmop));
538     aop->type = type;
539     return aop;
540 }
541
542 static void genSetDPTR(int n)
543 {
544     if (!n)
545     {
546         pic16_emitcode(";", "Select standard DPTR");
547         pic16_emitcode("mov", "dps, #0x00");
548     }
549     else
550     {
551         pic16_emitcode(";", "Select alternate DPTR");
552         pic16_emitcode("mov", "dps, #0x01");
553     }
554 }
555
556 /*-----------------------------------------------------------------*/
557 /* resolveIfx - converts an iCode ifx into a form more useful for  */
558 /*              generating code                                    */
559 /*-----------------------------------------------------------------*/
560 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
561 {
562   FENTRY2;
563   
564 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
565
566   if(!resIfx) 
567     return;
568
569
570   resIfx->condition = 1;    /* assume that the ifx is true */
571   resIfx->generated = 0;    /* indicate that the ifx has not been used */
572
573   if(!ifx) {
574     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
575
576 #if 1
577     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
578                         __FUNCTION__,__LINE__,resIfx->lbl->key);
579 #endif
580
581   } else {
582     if(IC_TRUE(ifx)) {
583       resIfx->lbl = IC_TRUE(ifx);
584     } else {
585       resIfx->lbl = IC_FALSE(ifx);
586       resIfx->condition = 0;
587     }
588
589 #if 1
590     if(IC_TRUE(ifx)) 
591       DEBUGpic16_emitcode("; +++","ifx true is non-null");
592     else
593       DEBUGpic16_emitcode("; +++","ifx true is null");
594     if(IC_FALSE(ifx)) 
595       DEBUGpic16_emitcode("; +++","ifx false is non-null");
596     else
597       DEBUGpic16_emitcode("; +++","ifx false is null");
598 #endif
599   }
600
601   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
602
603 }
604 #if 0
605 /*-----------------------------------------------------------------*/
606 /* pointerCode - returns the code for a pointer type               */
607 /*-----------------------------------------------------------------*/
608 static int pointerCode (sym_link *etype)
609 {
610
611     return PTR_TYPE(SPEC_OCLS(etype));
612
613 }
614 #endif
615
616 /*-----------------------------------------------------------------*/
617 /* aopForSym - for a true symbol                                   */
618 /*-----------------------------------------------------------------*/
619 static asmop *aopForSym (iCode *ic, operand *op, bool result)
620 {
621     symbol *sym=OP_SYMBOL(op);
622     asmop *aop;
623     memmap *space= SPEC_OCLS(sym->etype);
624
625     FENTRY2;
626     
627     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
628     
629 //    sym = OP_SYMBOL(op);
630
631     /* if already has one */
632     if (sym->aop) {
633             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
634         return sym->aop;
635     }
636
637 #if 0
638     /* if symbol was initially placed onStack then we must re-place it
639      * to direct memory, since pic16 does not have a specific stack */
640     if(sym->onStack) {
641         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
642     }
643 #endif
644
645
646 #if 0
647     if(sym->iaccess) {
648       if(space->paged) {
649         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
650
651         sym->aop = aop = newAsmop (AOP_PAGED);
652         aop->aopu.aop_dir = sym->rname ;
653         aop->size = getSize(sym->type);
654         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
655         pic16_allocDirReg( IC_LEFT(ic) );
656         return aop;
657       }
658       assert( 0 );
659     }
660 #endif
661     
662 #if 1
663     /* assign depending on the storage class */
664     /* if it is on the stack or indirectly addressable */
665     /* space we need to assign either r0 or r1 to it   */    
666     if (sym->onStack)   // || sym->iaccess)
667     {
668       pCodeOp *pcop[4];
669       int i;
670       
671         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
672                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
673         
674         /* acquire a temporary register -- it is saved in function */
675
676         sym->aop = aop = newAsmop(AOP_STA);
677         aop->aopu.stk.stk = sym->stack;
678         aop->size = getSize(sym->type);
679
680
681         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
682         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
683           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
684 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
685           
686           for(i=0;i<aop->size;i++)
687             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
688             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
689         } else
690         if(1 && ic->op == SEND) {
691
692           /* if SEND do the send here */
693           _G.resDirect = 1;
694         } else {
695           for(i=0;i<aop->size;i++) {
696             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
697             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
698           }
699         }
700
701
702 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
703
704 #if 1
705         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
706
707         // we do not need to load the value if it is to be defined...
708         if (result) return aop;
709
710         if(_G.accInUse) {
711                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
712         }
713         
714         for(i=0;i<aop->size;i++) {
715
716           /* initialise for stack access via frame pointer */
717           // operands on stack are accessible via "FSR2 + index" with index
718           // starting at 2 for arguments and growing from 0 downwards for
719           // local variables (index == 0 is not assigned so we add one here)
720           {
721             int soffs = sym->stack;
722             if (soffs <= 0) {
723               assert (soffs < 0);
724               soffs++;
725             } // if
726
727             if(1 && ic->op == SEND) {
728               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
729               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
730                     pic16_popCopyReg( pic16_frame_plusw ),
731                     pic16_popCopyReg(pic16_stack_postdec )));
732             } else {
733               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
734               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
735                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
736             }
737           }
738         }
739         
740         if(_G.accInUse) {
741                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
742         }
743         
744         return (aop);
745 #endif
746
747 #if 0
748         /* now assign the address of the variable to 
749         the pointer register */
750         if (aop->type != AOP_STK) {
751
752             if (sym->onStack) {
753                     if ( _G.accInUse )
754                         pic16_emitcode("push","acc");
755
756                     pic16_emitcode("mov","a,_bp");
757                     pic16_emitcode("add","a,#0x%02x",
758                              ((sym->stack < 0) ?
759                               ((char)(sym->stack - _G.nRegsSaved )) :
760                               ((char)sym->stack)) & 0xff);
761                     pic16_emitcode("mov","%s,a",
762                              aop->aopu.aop_ptr->name);
763
764                     if ( _G.accInUse )
765                         pic16_emitcode("pop","acc");
766             } else
767                 pic16_emitcode("mov","%s,#%s",
768                          aop->aopu.aop_ptr->name,
769                          sym->rname);
770             aop->paged = space->paged;
771         } else
772             aop->aopu.aop_stk = sym->stack;
773         return aop;
774 #endif
775
776     }
777 #endif
778
779 #if 0
780     if (sym->onStack && options.stack10bit)
781     {
782         /* It's on the 10 bit stack, which is located in
783          * far data space.
784          */
785          
786       //DEBUGpic16_emitcode(";","%d",__LINE__);
787
788         if ( _G.accInUse )
789                 pic16_emitcode("push","acc");
790
791         pic16_emitcode("mov","a,_bp");
792         pic16_emitcode("add","a,#0x%02x",
793                  ((sym->stack < 0) ?
794                    ((char)(sym->stack - _G.nRegsSaved )) :
795                    ((char)sym->stack)) & 0xff);
796         
797         genSetDPTR(1);
798         pic16_emitcode ("mov","dpx1,#0x40");
799         pic16_emitcode ("mov","dph1,#0x00");
800         pic16_emitcode ("mov","dpl1, a");
801         genSetDPTR(0);
802         
803         if ( _G.accInUse )
804             pic16_emitcode("pop","acc");
805             
806         sym->aop = aop = newAsmop(AOP_DPTR2);
807         aop->size = getSize(sym->type); 
808         return aop;
809     }
810 #endif
811
812 #if 1
813     /* special case for a function */
814     if (IS_FUNC(sym->type)) {   
815         sym->aop = aop = newAsmop(AOP_PCODE);
816         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
817         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
818         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
819         PCOI(aop->aopu.pcop)->index = 0;
820         aop->size = FPTRSIZE; 
821         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
822         return aop;
823     }
824 #endif
825
826
827
828     //DEBUGpic16_emitcode(";","%d",__LINE__);
829     /* if in bit space */
830     if (IN_BITSPACE(space)) {
831         sym->aop = aop = newAsmop (AOP_CRY);
832         aop->aopu.aop_dir = sym->rname ;
833         aop->size = getSize(sym->type);
834         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
835         return aop;
836     }
837     /* if it is in direct space */
838     if (IN_DIRSPACE(space)) {
839         sym->aop = aop = newAsmop (AOP_DIR);
840         aop->aopu.aop_dir = sym->rname ;
841         aop->size = getSize(sym->type);
842         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
843         pic16_allocDirReg( IC_LEFT(ic) );
844         return aop;
845     }
846
847
848     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
849         sym->aop = aop = newAsmop (AOP_DIR);
850         aop->aopu.aop_dir = sym->rname ;
851         aop->size = getSize(sym->type);
852         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853         pic16_allocDirReg( IC_LEFT(ic) );
854         return aop;
855     }
856
857
858     /* only remaining is far space */
859     sym->aop = aop = newAsmop(AOP_PCODE);
860
861 /* change the next if to 1 to revert to good old immediate code */
862         if(IN_CODESPACE(space)) {
863                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
864                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
865                 PCOI(aop->aopu.pcop)->index = 0;
866         } else {
867                 /* try to allocate via direct register */
868                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
869 //              aop->size = getSize( sym->type );
870         }
871
872         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
873                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
874
875 #if 0
876         if(!pic16_allocDirReg (IC_LEFT(ic)))
877                 return NULL;
878 #endif
879
880         if(IN_DIRSPACE( space ))
881                 aop->size = PTRSIZE;
882         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
883                 aop->size = FPTRSIZE;
884         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
885         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
886         else if(sym->onStack) {
887                 aop->size = PTRSIZE;
888         } else {
889           if(SPEC_SCLS(sym->etype) == S_PDATA) {
890             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
891             aop->size = FPTRSIZE;
892           } else
893                 assert( 0 );
894         }
895
896     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
897
898     /* if it is in code space */
899     if (IN_CODESPACE(space))
900         aop->code = 1;
901
902     return aop;     
903 }
904
905 /*-----------------------------------------------------------------*/
906 /* aopForRemat - rematerialzes an object                           */
907 /*-----------------------------------------------------------------*/
908 static asmop *aopForRemat (operand *op) // x symbol *sym)
909 {
910   symbol *sym = OP_SYMBOL(op);
911   operand *refop;
912   iCode *ic = NULL, *oldic;
913   asmop *aop = newAsmop(AOP_PCODE);
914   int val = 0;
915   int offset = 0;
916   int viaimmd=0;
917
918     FENTRY2;
919     
920         ic = sym->rematiCode;
921
922         if(IS_OP_POINTER(op)) {
923                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
924         }
925
926         for (;;) {
927                 oldic = ic;
928
929 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
930         
931                 if (ic->op == '+') {
932                         val += (int) operandLitValue(IC_RIGHT(ic));
933                 } else if (ic->op == '-') {
934                         val -= (int) operandLitValue(IC_RIGHT(ic));
935                 } else
936                         break;
937                 
938                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
939         }
940
941         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
942         refop = IC_LEFT(ic);
943
944         if(!op->isaddr)viaimmd++; else viaimmd=0;
945                 
946 /* set the following if to 1 to revert to good old immediate code */
947         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
948                 || viaimmd) {
949
950                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
951
952                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
953
954 #if 0
955                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
956 #else
957                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
958 #endif
959
960                 PCOI(aop->aopu.pcop)->index = val;
961                 
962                 aop->size = getSize( sym->type );
963         } else {
964                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
965
966                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
967                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
968
969                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
970         }
971
972
973         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
974                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
975 #if 0
976                 val, IS_PTR_CONST(operandType(op)));
977 #else
978                 val, IS_CODEPTR(operandType(op)));
979 #endif
980
981 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
982
983         pic16_allocDirReg (IC_LEFT(ic));
984
985         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
986                 aop->code = 1;
987
988   return aop;        
989 }
990
991 #if 0
992 static int aopIdx (asmop *aop, int offset)
993 {
994   if(!aop)
995     return -1;
996
997   if(aop->type !=  AOP_REG)
998     return -2;
999         
1000   return aop->aopu.aop_reg[offset]->rIdx;
1001
1002 }
1003 #endif
1004
1005 /*-----------------------------------------------------------------*/
1006 /* regsInCommon - two operands have some registers in common       */
1007 /*-----------------------------------------------------------------*/
1008 static bool regsInCommon (operand *op1, operand *op2)
1009 {
1010     symbol *sym1, *sym2;
1011     int i;
1012
1013     /* if they have registers in common */
1014     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1015         return FALSE ;
1016
1017     sym1 = OP_SYMBOL(op1);
1018     sym2 = OP_SYMBOL(op2);
1019
1020     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1021         return FALSE ;
1022
1023     for (i = 0 ; i < sym1->nRegs ; i++) {
1024         int j;
1025         if (!sym1->regs[i])
1026             continue ;
1027
1028         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1029             if (!sym2->regs[j])
1030                 continue ;
1031
1032             if (sym2->regs[j] == sym1->regs[i])
1033                 return TRUE ;
1034         }
1035     }
1036
1037     return FALSE ;
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* operandsEqu - equivalent                                        */
1042 /*-----------------------------------------------------------------*/
1043 static bool operandsEqu ( operand *op1, operand *op2)
1044 {
1045     symbol *sym1, *sym2;
1046
1047     /* if they not symbols */
1048     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1049         return FALSE;
1050
1051     sym1 = OP_SYMBOL(op1);
1052     sym2 = OP_SYMBOL(op2);
1053
1054     /* if both are itemps & one is spilt
1055        and the other is not then false */
1056     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1057         sym1->isspilt != sym2->isspilt )
1058         return FALSE ;
1059
1060     /* if they are the same */
1061     if (sym1 == sym2)
1062         return TRUE ;
1063
1064     if (sym1->rname[0] && sym2->rname[0]
1065         && strcmp (sym1->rname, sym2->rname) == 0)
1066         return TRUE;
1067
1068
1069     /* if left is a tmp & right is not */
1070     if (IS_ITEMP(op1)  && 
1071         !IS_ITEMP(op2) &&
1072         sym1->isspilt  &&
1073         (sym1->usl.spillLoc == sym2))
1074         return TRUE;
1075
1076     if (IS_ITEMP(op2)  && 
1077         !IS_ITEMP(op1) &&
1078         sym2->isspilt  &&
1079         sym1->level > 0 &&
1080         (sym2->usl.spillLoc == sym1))
1081         return TRUE ;
1082
1083     return FALSE ;
1084 }
1085
1086 /*-----------------------------------------------------------------*/
1087 /* pic16_sameRegs - two asmops have the same registers                   */
1088 /*-----------------------------------------------------------------*/
1089 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1090 {
1091     int i;
1092
1093     if (aop1 == aop2)
1094         return TRUE ;
1095
1096     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1097                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1098
1099     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1100
1101     if (aop1->type != AOP_REG ||
1102         aop2->type != AOP_REG )
1103         return FALSE ;
1104
1105     /* This is a bit too restrictive if one is a subset of the other...
1106     if (aop1->size != aop2->size )
1107         return FALSE ;
1108     */
1109
1110     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1111 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1112
1113 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1114         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1115             return FALSE ;
1116     }
1117
1118     return TRUE ;
1119 }
1120
1121 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1122 {
1123     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1124                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1125
1126     if(aop1 == aop2)return TRUE;
1127     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1128       
1129       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1130     
1131   return TRUE;
1132 }
1133
1134
1135 /*-----------------------------------------------------------------*/
1136 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1137 /*-----------------------------------------------------------------*/
1138 void pic16_aopOp (operand *op, iCode *ic, bool result)
1139 {
1140     asmop *aop;
1141     symbol *sym;
1142     int i;
1143
1144     if (!op)
1145         return ;
1146
1147     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1148
1149     /* if this a literal */
1150     if (IS_OP_LITERAL(op)) {
1151         op->aop = aop = newAsmop(AOP_LIT);
1152         aop->aopu.aop_lit = op->operand.valOperand;
1153         aop->size = getSize(operandType(op));
1154         return;
1155     }
1156
1157     {
1158       sym_link *type = operandType(op);
1159 #if 0
1160       if(IS_PTR_CONST(type))
1161 #else
1162       if(IS_CODEPTR(type))
1163 #endif
1164         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1165     }
1166
1167     /* if already has a asmop then continue */
1168     if (op->aop)
1169         return ;
1170
1171     /* if the underlying symbol has a aop */
1172     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1173       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1174         op->aop = OP_SYMBOL(op)->aop;
1175         return;
1176     }
1177
1178     /* if this is a true symbol */
1179     if (IS_TRUE_SYMOP(op)) {    
1180         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1181       op->aop = aopForSym(ic, op, result);
1182       return ;
1183     }
1184
1185     /* this is a temporary : this has
1186     only four choices :
1187     a) register
1188     b) spillocation
1189     c) rematerialize 
1190     d) conditional   
1191     e) can be a return use only */
1192
1193     sym = OP_SYMBOL(op);
1194
1195     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1196     /* if the type is a conditional */
1197     if (sym->regType == REG_CND) {
1198         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1199         aop->size = 0;
1200         return;
1201     }
1202
1203     /* if it is spilt then two situations
1204     a) is rematerialize 
1205     b) has a spill location */
1206     if (sym->isspilt || sym->nRegs == 0) {
1207
1208 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1209       DEBUGpic16_emitcode(";","%d",__LINE__);
1210         /* rematerialize it NOW */
1211         if (sym->remat) {
1212
1213             sym->aop = op->aop = aop = aopForRemat (op);
1214 //            aop->size = getSize(sym->type);
1215 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1216             return;
1217         }
1218
1219 #if 1
1220         if (sym->accuse) {
1221             int i;
1222             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1223             aop->size = getSize(sym->type);
1224             for ( i = 0 ; i < 1 ; i++ ) {
1225                 aop->aopu.aop_str[i] = accUse[i];
1226 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1227             }
1228             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1229             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1230             return;  
1231         }
1232 #endif
1233
1234 #if 1
1235         if (sym->ruonly) {
1236           /*
1237           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1238           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1239           //pic16_allocDirReg (IC_LEFT(ic));
1240           aop->size = getSize(sym->type);
1241           */
1242
1243           unsigned i;
1244
1245           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1246           aop->size = getSize(sym->type);
1247           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1248             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1249
1250           DEBUGpic16_emitcode(";","%d",__LINE__);
1251           return;
1252         }
1253 #endif
1254         /* else spill location  */
1255         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1256             /* force a new aop if sizes differ */
1257             sym->usl.spillLoc->aop = NULL;
1258         }
1259
1260 #if 0
1261         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1262                             __FUNCTION__,__LINE__,
1263                             sym->usl.spillLoc->rname,
1264                             sym->rname, sym->usl.spillLoc->offset);
1265 #endif
1266
1267         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1268         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1269         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1270           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1271                                                   getSize(sym->type), 
1272                                                   sym->usl.spillLoc->offset, op);
1273         } else {
1274           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1275           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1276           assert (getSize(sym->type) <= 1);
1277           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1278         }
1279         aop->size = getSize(sym->type);
1280
1281         return;
1282     }
1283
1284     {
1285       sym_link *type = operandType(op);
1286 #if 0
1287       if(IS_PTR_CONST(type)) 
1288 #else
1289       if(IS_CODEPTR(type)) 
1290 #endif
1291         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1292     }
1293
1294     /* must be in a register */
1295     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1296     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1297     aop->size = sym->nRegs;
1298     for ( i = 0 ; i < sym->nRegs ;i++)
1299         aop->aopu.aop_reg[i] = sym->regs[i];
1300 }
1301
1302 /*-----------------------------------------------------------------*/
1303 /* pic16_freeAsmop - free up the asmop given to an operand               */
1304 /*----------------------------------------------------------------*/
1305 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1306 {   
1307     asmop *aop ;
1308
1309     if (!op)
1310         aop = aaop;
1311     else 
1312         aop = op->aop;
1313
1314     if (!aop)
1315         return ;
1316
1317     if (aop->freed)
1318         goto dealloc; 
1319
1320     aop->freed = 1;
1321
1322     /* depending on the asmop type only three cases need work AOP_RO
1323        , AOP_R1 && AOP_STK */
1324 #if 1
1325     switch (aop->type) {
1326         case AOP_FSR0 :
1327             if (_G.fsr0Pushed ) {
1328                 if (pop) {
1329                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1330                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1331 //                    pic16_emitcode ("pop","ar0");
1332                     _G.fsr0Pushed--;
1333                 }
1334             }
1335             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1336             break;
1337
1338         case AOP_FSR2 :
1339             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1340             break;
1341
1342         case AOP_R0 :
1343             if (_G.r0Pushed ) {
1344                 if (pop) {
1345                     pic16_emitcode ("pop","ar0");     
1346                     _G.r0Pushed--;
1347                 }
1348             }
1349             bitVectUnSetBit(ic->rUsed,R0_IDX);
1350             break;
1351
1352         case AOP_R1 :
1353             if (_G.r1Pushed ) {
1354                 if (pop) {
1355                     pic16_emitcode ("pop","ar1");
1356                     _G.r1Pushed--;
1357                 }
1358             }
1359             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1360             break;
1361
1362         case AOP_STA:
1363           {
1364             int i;
1365
1366               /* we must store the result on stack */
1367               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1368                 // operands on stack are accessible via "FSR2 + index" with index
1369                 // starting at 2 for arguments and growing from 0 downwards for
1370                 // local variables (index == 0 is not assigned so we add one here)
1371                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1372                 if (soffs <= 0) {
1373                   assert (soffs < 0);
1374                   soffs++;
1375                 } // if
1376                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1377                 for(i=0;i<aop->size;i++) {
1378                   /* initialise for stack access via frame pointer */
1379                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1380                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1381                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1382                 }
1383         
1384                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1385               }
1386
1387               if(!_G.resDirect) {
1388                 for(i=0;i<aop->size;i++) {
1389                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1390
1391                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1392                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1393                 }
1394                   
1395               }
1396               _G.resDirect = 0;
1397           }
1398           break;
1399 #if 0
1400         case AOP_STK :
1401         {
1402             int sz = aop->size;    
1403             int stk = aop->aopu.aop_stk + aop->size;
1404             bitVectUnSetBit(ic->rUsed,R0_IDX);
1405             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1406
1407             getFreePtr(ic,&aop,FALSE);
1408             
1409             if (options.stack10bit)
1410             {
1411                 /* I'm not sure what to do here yet... */
1412                 /* #STUB */
1413                 fprintf(stderr, 
1414                         "*** Warning: probably generating bad code for "
1415                         "10 bit stack mode.\n");
1416             }
1417             
1418             if (stk) {
1419                 pic16_emitcode ("mov","a,_bp");
1420                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1421                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1422             } else {
1423                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1424             }
1425
1426             while (sz--) {
1427                 pic16_emitcode("pop","acc");
1428                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1429                 if (!sz) break;
1430                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1431             }
1432             op->aop = aop;
1433             pic16_freeAsmop(op,NULL,ic,TRUE);
1434             if (_G.r0Pushed) {
1435                 pic16_emitcode("pop","ar0");
1436                 _G.r0Pushed--;
1437             }
1438
1439             if (_G.r1Pushed) {
1440                 pic16_emitcode("pop","ar1");
1441                 _G.r1Pushed--;
1442             }       
1443         }
1444 #endif
1445
1446     }
1447 #endif
1448
1449 dealloc:
1450     /* all other cases just dealloc */
1451     if (op ) {
1452         op->aop = NULL;
1453         if (IS_SYMOP(op)) {
1454             OP_SYMBOL(op)->aop = NULL;    
1455             /* if the symbol has a spill */
1456             if (SPIL_LOC(op))
1457                 SPIL_LOC(op)->aop = NULL;
1458         }
1459     }
1460 }
1461
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_aopGet - for fetching value of the aop                          */
1464 /*-----------------------------------------------------------------*/
1465 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1466 {
1467     char *s = buffer ;
1468     char *rs;
1469
1470     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1471
1472     /* offset is greater than size then zero */
1473     if (offset > (aop->size - 1) &&
1474         aop->type != AOP_LIT)
1475         return zero;
1476
1477     /* depending on type */
1478     switch (aop->type) {
1479
1480     case AOP_FSR0:
1481     case AOP_FSR2:
1482       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1483       rs = Safe_calloc(1, strlen(s)+1);
1484       strcpy(rs, s);
1485       return (rs);
1486       
1487 #if 0
1488       /* if we need to increment it */
1489       while (offset > aop->coff)
1490         {
1491           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1492           aop->coff++;
1493         }
1494
1495       while (offset < aop->coff)
1496         {
1497           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1498           aop->coff--;
1499         }
1500       aop->coff = offset;
1501       if (aop->paged)
1502         {
1503           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1504           return (dname ? "acc" : "a");
1505         }
1506       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1507       rs = Safe_calloc (1, strlen (s) + 1);
1508       strcpy (rs, s);
1509       return rs;
1510 #endif
1511
1512         
1513     case AOP_IMMD:
1514         if (bit16) 
1515             sprintf (s,"%s",aop->aopu.aop_immd);
1516         else
1517             if (offset) 
1518                 sprintf(s,"(%s >> %d)",
1519                         aop->aopu.aop_immd,
1520                         offset*8);
1521             else
1522                 sprintf(s,"%s",
1523                         aop->aopu.aop_immd);
1524         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1525         rs = Safe_calloc(1,strlen(s)+1);
1526         strcpy(rs,s);   
1527         return rs;
1528         
1529     case AOP_DIR:
1530       if (offset) {
1531         sprintf(s,"(%s + %d)",
1532                 aop->aopu.aop_dir,
1533                 offset);
1534         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1535       } else
1536             sprintf(s,"%s",aop->aopu.aop_dir);
1537         rs = Safe_calloc(1,strlen(s)+1);
1538         strcpy(rs,s);   
1539         return rs;
1540         
1541     case AOP_REG:
1542       //if (dname) 
1543       //    return aop->aopu.aop_reg[offset]->dname;
1544       //else
1545             return aop->aopu.aop_reg[offset]->name;
1546         
1547     case AOP_CRY:
1548       //pic16_emitcode(";","%d",__LINE__);
1549       return aop->aopu.aop_dir;
1550         
1551     case AOP_ACC:
1552         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1553 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1554 //        assert( 0 );
1555 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1556         rs = Safe_strdup("WREG");
1557         return (rs);
1558
1559     case AOP_LIT:
1560         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1561         rs = Safe_calloc(1,strlen(s)+1);
1562         strcpy(rs,s);   
1563         return rs;
1564         
1565     case AOP_STR:
1566         aop->coff = offset ;
1567
1568 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1569 //          dname)
1570 //          return "acc";
1571         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1572           aop->type = AOP_ACC;
1573           return Safe_strdup("WREG");
1574         }
1575         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1576         
1577         return aop->aopu.aop_str[offset];
1578         
1579     case AOP_PCODE:
1580       {
1581         pCodeOp *pcop = aop->aopu.pcop;
1582         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1583         if(pcop->name) {
1584           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1585           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1586           if (offset) {
1587             sprintf(s,"(%s + %d)", pcop->name, offset);
1588           } else {
1589             sprintf(s,"%s", pcop->name);
1590           }
1591         } else
1592           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1593
1594       }
1595       rs = Safe_calloc(1,strlen(s)+1);
1596       strcpy(rs,s);   
1597       return rs;
1598
1599 #if 0
1600     case AOP_PAGED:
1601       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1602       if (offset) {
1603         sprintf(s,"(%s + %d)",
1604                 aop->aopu.aop_dir,
1605                 offset);
1606       } else
1607             sprintf(s,"%s",aop->aopu.aop_dir);
1608       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1609       rs = Safe_calloc(1,strlen(s)+1);
1610       strcpy(rs,s);   
1611       return rs;
1612 #endif
1613
1614     case AOP_STA:
1615         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1616         return (rs);
1617         
1618     case AOP_STK:
1619 //        pCodeOp *pcop = aop->aop
1620         break;
1621
1622     }
1623
1624     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1625     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626            "aopget got unsupported aop->type");
1627     exit(0);
1628 }
1629
1630
1631
1632 /* lock has the following meaning: When allocating temporary registers
1633  * for stack variables storage, the value of the temporary register is
1634  * saved on stack. Its value is restored at the end. This procedure is
1635  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1636  * a possibility that before a call to pic16_aopOp, a temporary register
1637  * is allocated for a while and it is freed after some time, this will
1638  * mess the stack and values will not be restored properly. So use lock=1
1639  * to allocate temporary registers used internally by the programmer, and
1640  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1641  * to inform the compiler developer about a possible bug. This is an internal
1642  * feature for developing the compiler -- VR */
1643  
1644 int _TempReg_lock = 0;
1645 /*-----------------------------------------------------------------*/
1646 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1647 /*-----------------------------------------------------------------*/
1648 pCodeOp *pic16_popGetTempReg(int lock)
1649 {
1650   pCodeOp *pcop;
1651   symbol *cfunc;
1652
1653 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1654     if(_TempReg_lock) {
1655 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1656     }
1657     
1658     _TempReg_lock += lock;
1659     
1660     cfunc = currFunc;
1661     currFunc = NULL;
1662
1663     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1664     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1665       PCOR(pcop)->r->wasUsed=1;
1666       PCOR(pcop)->r->isFree=0;
1667
1668       /* push value on stack */
1669       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1670     }
1671
1672     currFunc = cfunc;
1673
1674   return pcop;
1675 }
1676
1677 /*-----------------------------------------------------------------*/
1678 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1679 /*                           is not part of f, but don't save if   */
1680 /*                           inside v                              */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1683 {
1684   pCodeOp *pcop=NULL;
1685   symbol *cfunc;
1686   int i;
1687
1688 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1689
1690     if(_TempReg_lock) {
1691 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1692     }
1693
1694     _TempReg_lock += lock;
1695
1696     cfunc = currFunc;
1697     currFunc = NULL;
1698
1699     i = bitVectFirstBit(f);
1700     while(i < 128) {
1701
1702       /* bypass registers that are used by function */
1703       if(!bitVectBitValue(f, i)) {
1704       
1705         /* bypass registers that are already allocated for stack access */
1706         if(!bitVectBitValue(v, i))  {
1707         
1708 //          debugf("getting register rIdx = %d\n", i);
1709           /* ok, get the operand */
1710           pcop = pic16_newpCodeOpReg( i );
1711     
1712           /* should never by NULL */
1713           assert( pcop != NULL );
1714
1715           
1716           /* sanity check */
1717           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1718             int found=0;
1719             
1720               PCOR(pcop)->r->wasUsed=1;
1721               PCOR(pcop)->r->isFree=0;
1722
1723
1724               {
1725                 regs *sr;
1726               
1727                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1728
1729                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1730                       /* already used in previous steps, break */
1731                       found=1;          
1732                       break;
1733                     }
1734                   }
1735               }
1736
1737               /* caller takes care of the following */
1738 //              bitVectSetBit(v, i);
1739
1740               if(!found) {
1741                 /* push value on stack */
1742                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1743                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1744               }
1745           
1746             break;
1747           }
1748         }
1749       }
1750       i++;
1751     }
1752
1753     currFunc = cfunc;
1754
1755   return pcop;
1756 }
1757
1758
1759 /*-----------------------------------------------------------------*/
1760 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1761 /*-----------------------------------------------------------------*/
1762 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1763 {
1764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1765
1766   _TempReg_lock -= lock;
1767
1768   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1769     PCOR(pcop)->r->isFree = 1;
1770
1771     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1772   }
1773 }
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetLabel(unsigned int key)
1778 {
1779
1780   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1781
1782   if(key>max_key)
1783     max_key = key;
1784
1785   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1786 }
1787
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popCopyReg - copy a pcode operator                              */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1792 {
1793   pCodeOpReg *pcor;
1794
1795   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1796   memcpy (pcor, pc, sizeof (pCodeOpReg));
1797   pcor->r->wasUsed = 1;
1798   
1799   //pcor->pcop.type = pc->pcop.type;
1800   if(pc->pcop.name) {
1801     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1802       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1803   } else
1804     pcor->pcop.name = NULL;
1805
1806   //pcor->r = pc->r;
1807   //pcor->rIdx = pc->rIdx;
1808   //pcor->r->wasUsed=1;
1809   //pcor->instance = pc->instance;
1810
1811 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1812
1813   return PCOP(pcor);
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGetLit(int lit)
1820 {
1821   return pic16_newpCodeOpLit(lit);
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1826 /*-----------------------------------------------------------------*/
1827 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1828 {
1829   return pic16_newpCodeOpLit2(lit, arg2);
1830 }
1831
1832
1833 /*-----------------------------------------------------------------*/
1834 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1835 /*-----------------------------------------------------------------*/
1836 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1837 {
1838   return pic16_newpCodeOpImmd(name, offset,index, 0);
1839 }
1840
1841
1842 /*-----------------------------------------------------------------*/
1843 /* pic16_popGet - asm operator to pcode operator conversion              */
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *pic16_popGetWithString(char *str)
1846 {
1847   pCodeOp *pcop;
1848
1849
1850   if(!str) {
1851     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1852     exit (1);
1853   }
1854
1855   pcop = pic16_newpCodeOp(str,PO_STR);
1856
1857   return pcop;
1858 }
1859
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popRegFromString -                                        */
1862 /*-----------------------------------------------------------------*/
1863 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1864 {
1865
1866   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1867   pcop->type = PO_DIR;
1868
1869   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1870   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1871
1872   if(!str)
1873     str = "BAD_STRING";
1874
1875   pcop->name = Safe_calloc(1,strlen(str)+1);
1876   strcpy(pcop->name,str);
1877
1878   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1879
1880   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1881
1882   /* make sure that register doesn't exist,
1883    * and operand isn't NULL
1884    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1885   if((PCOR(pcop)->r == NULL) 
1886     && (op)
1887     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1888 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1889 //              __FUNCTION__, __LINE__, str, size, offset);
1890
1891     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1892     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1893
1894   }
1895   PCOR(pcop)->instance = offset;
1896
1897   return pcop;
1898 }
1899
1900 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1901 {
1902   pCodeOp *pcop;
1903
1904 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1905
1906         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907         PCOR(pcop)->rIdx = rIdx;
1908         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1909
1910         PCOR(pcop)->r->isFree = 0;
1911         PCOR(pcop)->r->wasUsed = 1;
1912
1913         pcop->type = PCOR(pcop)->r->pc_type;
1914
1915   return pcop;
1916 }
1917
1918 /*---------------------------------------------------------------------------------*/
1919 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1920 /*                 VR 030601                                                       */
1921 /*---------------------------------------------------------------------------------*/
1922 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1923 {
1924   pCodeOpReg2 *pcop2;
1925   pCodeOp *temp;
1926   
1927         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1928
1929         /* comment the following check, so errors to throw up */
1930 //      if(!pcop2)return NULL;
1931
1932         temp = pic16_popGet(aop_dst, offset);
1933         pcop2->pcop2 = temp;
1934         
1935   return PCOP(pcop2);
1936 }
1937
1938
1939
1940 /*--------------------------------------------------------------------------------.-*/
1941 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1942 /*                  VR 030601 , adapted by Hans Dorn                                */
1943 /*--------------------------------------------------------------------------------.-*/
1944 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1945 {
1946   pCodeOpReg2 *pcop2;
1947  
1948         pcop2 = (pCodeOpReg2 *)src;
1949         pcop2->pcop2 = dst;
1950         
1951         return PCOP(pcop2);
1952 }
1953
1954
1955
1956 /*---------------------------------------------------------------------------------*/
1957 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1958 /*                     movff instruction                                           */
1959 /*---------------------------------------------------------------------------------*/
1960 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1961 {
1962   pCodeOpReg2 *pcop2;
1963
1964         if(!noalloc) {
1965                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1966                 pcop2->pcop2 = pic16_popCopyReg(dst);
1967         } else {
1968                 /* the pCodeOp may be already allocated */
1969                 pcop2 = (pCodeOpReg2 *)(src);
1970                 pcop2->pcop2 = (pCodeOp *)(dst);
1971         }
1972
1973   return PCOP(pcop2);
1974 }
1975
1976
1977 /*-----------------------------------------------------------------*/
1978 /* pic16_popGet - asm operator to pcode operator conversion              */
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1981 {
1982   //char *s = buffer ;
1983   char *rs;
1984   pCodeOp *pcop;
1985
1986     FENTRY2;
1987     /* offset is greater than
1988     size then zero */
1989
1990 //    if (offset > (aop->size - 1) &&
1991 //        aop->type != AOP_LIT)
1992 //      return NULL;  //zero;
1993
1994     /* depending on type */
1995     switch (aop->type) {
1996         
1997     case AOP_R0:
1998     case AOP_R1:
1999     case AOP_DPTR:
2000     case AOP_DPTR2:
2001         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2002         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2003         assert( 0 );
2004         return NULL;
2005
2006
2007     case AOP_FSR0:
2008     case AOP_FSR2:
2009       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2010       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2011       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2012       PCOR(pcop)->r->wasUsed = 1;
2013       PCOR(pcop)->r->isFree = 0;
2014       
2015       PCOR(pcop)->instance = offset;
2016       pcop->type = PCOR(pcop)->r->pc_type;
2017       return (pcop);
2018
2019     case AOP_IMMD:
2020       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2021       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2022
2023     case AOP_STA:
2024       /* pCodeOp is already allocated from aopForSym */
2025         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2026         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2027           
2028       return (pcop);
2029       
2030     case AOP_ACC:
2031       {
2032         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2033
2034         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2035
2036         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2037         
2038         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2039         PCOR(pcop)->rIdx = rIdx;
2040         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2041         PCOR(pcop)->r->wasUsed=1;
2042         PCOR(pcop)->r->isFree=0;
2043
2044         PCOR(pcop)->instance = offset;
2045         pcop->type = PCOR(pcop)->r->pc_type;
2046 //      rs = aop->aopu.aop_reg[offset]->name;
2047 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2048         return pcop;
2049
2050
2051 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2052 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2053
2054 //      assert( 0 );
2055       }
2056         
2057     case AOP_DIR:
2058       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060         
2061 #if 0
2062     case AOP_PAGED:
2063       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2064       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2065 #endif
2066
2067     case AOP_REG:
2068       {
2069         int rIdx;
2070         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2071         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2072
2073         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2074         
2075         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2076 //      pcop->type = PO_GPR_REGISTER;
2077         PCOR(pcop)->rIdx = rIdx;
2078         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2079         PCOR(pcop)->r->wasUsed=1;
2080         PCOR(pcop)->r->isFree=0;
2081
2082         PCOR(pcop)->instance = offset;
2083         pcop->type = PCOR(pcop)->r->pc_type;
2084         
2085         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2086         rs = aop->aopu.aop_reg[offset]->name;
2087         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2088         return pcop;
2089       }
2090
2091     case AOP_CRY:
2092         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2093
2094       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2095       PCOR(pcop)->instance = offset;
2096       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2097       //if(PCOR(pcop)->r == NULL)
2098       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2099       return pcop;
2100         
2101     case AOP_LIT:
2102         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2103       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2104
2105     case AOP_STR:
2106       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2107       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108
2109       /*
2110       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2111       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2112       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113       pcop->type = PCOR(pcop)->r->pc_type;
2114       pcop->name = PCOR(pcop)->r->name;
2115
2116       return pcop;
2117       */
2118
2119     case AOP_PCODE:
2120       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2121                           __LINE__, 
2122                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2123       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2124       switch( aop->aopu.pcop->type ) {
2125         case PO_DIR: PCOR(pcop)->instance += offset; break;
2126         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2127         case PO_WREG:
2128             assert (offset==0);
2129             break;
2130         default:
2131           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2132           assert( 0 );  /* should never reach here */;
2133       }
2134       return pcop;
2135     }
2136
2137     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2138            "pic16_popGet got unsupported aop->type");
2139     exit(0);
2140 }
2141 /*-----------------------------------------------------------------*/
2142 /* pic16_aopPut - puts a string for a aop                                */
2143 /*-----------------------------------------------------------------*/
2144 void pic16_aopPut (asmop *aop, char *s, int offset)
2145 {
2146     char *d = buffer ;
2147     symbol *lbl ;
2148
2149     return;
2150
2151     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2152
2153     if (aop->size && offset > ( aop->size - 1)) {
2154         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2155                "pic16_aopPut got offset > aop->size");
2156         exit(0);
2157     }
2158
2159     /* will assign value to value */
2160     /* depending on where it is ofcourse */
2161     switch (aop->type) {
2162     case AOP_DIR:
2163       if (offset) {
2164         sprintf(d,"(%s + %d)",
2165                 aop->aopu.aop_dir,offset);
2166         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2167
2168       } else
2169             sprintf(d,"%s",aop->aopu.aop_dir);
2170         
2171         if (strcmp(d,s)) {
2172           DEBUGpic16_emitcode(";","%d",__LINE__);
2173           if(strcmp(s,"W"))
2174             pic16_emitcode("movf","%s,w",s);
2175           pic16_emitcode("movwf","%s",d);
2176
2177           if(strcmp(s,"W")) {
2178             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2179             if(offset >= aop->size) {
2180               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2181               break;
2182             } else
2183               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2184           }
2185
2186           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2187
2188
2189         }
2190         break;
2191         
2192     case AOP_REG:
2193       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2194         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2195           /*
2196             if (*s == '@'           ||
2197                 strcmp(s,"r0") == 0 ||
2198                 strcmp(s,"r1") == 0 ||
2199                 strcmp(s,"r2") == 0 ||
2200                 strcmp(s,"r3") == 0 ||
2201                 strcmp(s,"r4") == 0 ||
2202                 strcmp(s,"r5") == 0 ||
2203                 strcmp(s,"r6") == 0 || 
2204                 strcmp(s,"r7") == 0 )
2205                 pic16_emitcode("mov","%s,%s  ; %d",
2206                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2207             else
2208           */
2209
2210           if(strcmp(s,"W")==0 )
2211             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2212
2213           pic16_emitcode("movwf","%s",
2214                    aop->aopu.aop_reg[offset]->name);
2215
2216           if(strcmp(s,zero)==0) {
2217             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2218
2219           } else if(strcmp(s,"W")==0) {
2220             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2221             pcop->type = PO_GPR_REGISTER;
2222
2223             PCOR(pcop)->rIdx = -1;
2224             PCOR(pcop)->r = NULL;
2225
2226             DEBUGpic16_emitcode(";","%d",__LINE__);
2227             pcop->name = Safe_strdup(s);
2228             pic16_emitpcode(POC_MOVFW,pcop);
2229             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230           } else if(strcmp(s,one)==0) {
2231             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2233           } else {
2234             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2235           }
2236         }
2237         break;
2238         
2239     case AOP_DPTR:
2240     case AOP_DPTR2:
2241     
2242     if (aop->type == AOP_DPTR2)
2243     {
2244         genSetDPTR(1);
2245     }
2246     
2247         if (aop->code) {
2248             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2249                    "pic16_aopPut writting to code space");
2250             exit(0);
2251         }
2252         
2253         while (offset > aop->coff) {
2254             aop->coff++;
2255             pic16_emitcode ("inc","dptr");
2256         }
2257         
2258         while (offset < aop->coff) {
2259             aop->coff-- ;
2260             pic16_emitcode("lcall","__decdptr");
2261         }
2262         
2263         aop->coff = offset;
2264         
2265         /* if not in accumulater */
2266         MOVA(s);        
2267         
2268         pic16_emitcode ("movx","@dptr,a");
2269         
2270     if (aop->type == AOP_DPTR2)
2271     {
2272         genSetDPTR(0);
2273     }
2274         break;
2275         
2276     case AOP_R0:
2277     case AOP_R1:
2278         while (offset > aop->coff) {
2279             aop->coff++;
2280             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2281         }
2282         while (offset < aop->coff) {
2283             aop->coff-- ;
2284             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2285         }
2286         aop->coff = offset;
2287         
2288         if (aop->paged) {
2289             MOVA(s);           
2290             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2291             
2292         } else
2293             if (*s == '@') {
2294                 MOVA(s);
2295                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2296             } else
2297                 if (strcmp(s,"r0") == 0 ||
2298                     strcmp(s,"r1") == 0 ||
2299                     strcmp(s,"r2") == 0 ||
2300                     strcmp(s,"r3") == 0 ||
2301                     strcmp(s,"r4") == 0 ||
2302                     strcmp(s,"r5") == 0 ||
2303                     strcmp(s,"r6") == 0 || 
2304                     strcmp(s,"r7") == 0 ) {
2305                     char buffer[10];
2306                     sprintf(buffer,"a%s",s);
2307                     pic16_emitcode("mov","@%s,%s",
2308                              aop->aopu.aop_ptr->name,buffer);
2309                 } else
2310                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2311         
2312         break;
2313         
2314     case AOP_STK:
2315         if (strcmp(s,"a") == 0)
2316             pic16_emitcode("push","acc");
2317         else
2318             pic16_emitcode("push","%s",s);
2319         
2320         break;
2321         
2322     case AOP_CRY:
2323         /* if bit variable */
2324         if (!aop->aopu.aop_dir) {
2325             pic16_emitcode("clr","a");
2326             pic16_emitcode("rlc","a");
2327         } else {
2328             if (s == zero) 
2329                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2330             else
2331                 if (s == one)
2332                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2333                 else
2334                     if (!strcmp(s,"c"))
2335                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2336                     else {
2337                         lbl = newiTempLabel(NULL);
2338                         
2339                         if (strcmp(s,"a")) {
2340                             MOVA(s);
2341                         }
2342                         pic16_emitcode("clr","c");
2343                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2344                         pic16_emitcode("cpl","c");
2345                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2346                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2347                     }
2348         }
2349         break;
2350         
2351     case AOP_STR:
2352         aop->coff = offset;
2353         if (strcmp(aop->aopu.aop_str[offset],s))
2354             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2355         break;
2356         
2357     case AOP_ACC:
2358         aop->coff = offset;
2359         if (!offset && (strcmp(s,"acc") == 0))
2360             break;
2361         
2362         if (strcmp(aop->aopu.aop_str[offset],s))
2363             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2364         break;
2365
2366     default :
2367         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2368 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2369 //             "pic16_aopPut got unsupported aop->type");
2370 //      exit(0);    
2371     }    
2372
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2377 /*-----------------------------------------------------------------*/
2378 void pic16_mov2w (asmop *aop, int offset)
2379 {
2380   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2381
2382   if(is_LitAOp(aop))
2383     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2384   else
2385     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2386 }
2387
2388 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2389 {
2390   if(is_LitAOp(src)) {
2391     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2392     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2393   } else {
2394     if(pic16_sameRegsOfs(src, dst, offset))return;
2395     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2396                       pic16_popGet(dst, offset)));
2397   }
2398 }
2399
2400 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2401 {
2402   if(is_LitAOp(src)) {
2403     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2404     pic16_emitpcode(POC_MOVWF, dst);
2405   } else {
2406     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2407   }
2408 }
2409
2410 void pic16_testStackOverflow(void)
2411 {
2412 #define GSTACK_TEST_NAME        "_gstack_test"
2413
2414   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2415   
2416   {
2417     symbol *sym;
2418
2419       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2420       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2421 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2422       checkAddSym(&externs, sym);
2423   }
2424
2425 }
2426
2427 /* push pcop into stack */
2428 void pic16_pushpCodeOp(pCodeOp *pcop)
2429 {
2430 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2431   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2432   if(pic16_options.gstack)
2433     pic16_testStackOverflow();
2434     
2435 }
2436
2437 /* pop pcop from stack */
2438 void pic16_poppCodeOp(pCodeOp *pcop)
2439 {
2440   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2441   if(pic16_options.gstack)
2442     pic16_testStackOverflow();
2443 }
2444
2445
2446 /*-----------------------------------------------------------------*/
2447 /* pushw - pushes wreg to stack                                    */
2448 /*-----------------------------------------------------------------*/
2449 void pushw(void)
2450 {
2451   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2452   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2453   if(pic16_options.gstack)
2454     pic16_testStackOverflow();
2455 }
2456
2457                 
2458 /*-----------------------------------------------------------------*/
2459 /* pushaop - pushes aop to stack                                   */
2460 /*-----------------------------------------------------------------*/
2461 void pushaop(asmop *aop, int offset)
2462 {
2463   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2464
2465   if(is_LitAOp(aop)) {
2466     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2467     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2468   } else {
2469     pic16_emitpcode(POC_MOVFF,
2470       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2471   }
2472
2473   if(pic16_options.gstack)
2474     pic16_testStackOverflow();
2475 }
2476
2477 /*-----------------------------------------------------------------*/
2478 /* popaop - pops aop from stack                                    */
2479 /*-----------------------------------------------------------------*/
2480 void popaop(asmop *aop, int offset)
2481 {
2482   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2483   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2484   if(pic16_options.gstack)
2485     pic16_testStackOverflow();
2486 }
2487
2488 void popaopidx(asmop *aop, int offset, int index)
2489 {
2490   int ofs=1;
2491
2492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493
2494     if(STACK_MODEL_LARGE)ofs++;
2495
2496     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2497     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2498     if(pic16_options.gstack)
2499       pic16_testStackOverflow();
2500 }
2501
2502 #if !(USE_GENERIC_SIGNED_SHIFT)
2503 /*-----------------------------------------------------------------*/
2504 /* reAdjustPreg - points a register back to where it should        */
2505 /*-----------------------------------------------------------------*/
2506 static void reAdjustPreg (asmop *aop)
2507 {
2508     int size ;
2509
2510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511     aop->coff = 0;
2512     if ((size = aop->size) <= 1)
2513         return ;
2514     size-- ;
2515     switch (aop->type) {
2516         case AOP_R0 :
2517         case AOP_R1 :
2518             while (size--)
2519                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2520             break;          
2521         case AOP_DPTR :
2522         case AOP_DPTR2:
2523             if (aop->type == AOP_DPTR2)
2524             {
2525                 genSetDPTR(1);
2526             } 
2527             while (size--)
2528             {
2529                 pic16_emitcode("lcall","__decdptr");
2530             }
2531                 
2532             if (aop->type == AOP_DPTR2)
2533             {
2534                 genSetDPTR(0);
2535             }                
2536             break;  
2537
2538     }   
2539
2540 }
2541 #endif
2542
2543 #if 0
2544 /*-----------------------------------------------------------------*/
2545 /* opIsGptr: returns non-zero if the passed operand is             */   
2546 /* a generic pointer type.                                         */
2547 /*-----------------------------------------------------------------*/ 
2548 static int opIsGptr(operand *op)
2549 {
2550     sym_link *type = operandType(op);
2551     
2552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2553     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2554     {
2555         return 1;
2556     }
2557     return 0;        
2558 }
2559 #endif
2560
2561 /*-----------------------------------------------------------------*/
2562 /* pic16_getDataSize - get the operand data size                         */
2563 /*-----------------------------------------------------------------*/
2564 int pic16_getDataSize(operand *op)
2565 {
2566     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2567
2568
2569     return AOP_SIZE(op);
2570
2571     // tsd- in the pic port, the genptr size is 1, so this code here
2572     // fails. ( in the 8051 port, the size was 4).
2573 #if 0
2574     int size;
2575     size = AOP_SIZE(op);
2576     if (size == GPTRSIZE)
2577     {
2578         sym_link *type = operandType(op);
2579         if (IS_GENPTR(type))
2580         {
2581             /* generic pointer; arithmetic operations
2582              * should ignore the high byte (pointer type).
2583              */
2584             size--;
2585     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2586         }
2587     }
2588     return size;
2589 #endif
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* pic16_outAcc - output Acc                                             */
2594 /*-----------------------------------------------------------------*/
2595 void pic16_outAcc(operand *result)
2596 {
2597   int size,offset;
2598   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2599   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2600
2601
2602   size = pic16_getDataSize(result);
2603   if(size){
2604     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2605     size--;
2606     offset = 1;
2607     /* unsigned or positive */
2608     while(size--)
2609       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2610   }
2611
2612 }
2613
2614 /*-----------------------------------------------------------------*/
2615 /* pic16_outBitC - output a bit C                                  */
2616 /*                 Move to result the value of Carry flag -- VR    */
2617 /*-----------------------------------------------------------------*/
2618 void pic16_outBitC(operand *result)
2619 {
2620   int i;
2621
2622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2623
2624     /* if the result is bit */
2625     if (AOP_TYPE(result) == AOP_CRY) {
2626         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2627         pic16_aopPut(AOP(result),"c",0);
2628     } else {
2629
2630         i = AOP_SIZE(result);
2631         while(i--) {
2632                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2633         }
2634         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2635     }
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* pic16_outBitOp - output a bit from Op                           */
2640 /*                 Move to result the value of set/clr op -- VR    */
2641 /*-----------------------------------------------------------------*/
2642 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2643 {
2644   int i;
2645
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647
2648     /* if the result is bit */
2649     if (AOP_TYPE(result) == AOP_CRY) {
2650         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2651         pic16_aopPut(AOP(result),"c",0);
2652     } else {
2653
2654         i = AOP_SIZE(result);
2655         while(i--) {
2656                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2657         }
2658         pic16_emitpcode(POC_RRCF, pcop);          
2659         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2660     }
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_toBoolean(operand *oper)
2667 {
2668     int size = AOP_SIZE(oper) - 1;
2669     int offset = 1;
2670
2671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2672
2673     if ( AOP_TYPE(oper) != AOP_ACC) {
2674       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2675     }
2676     while (size--) {
2677       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2678     }
2679 }
2680
2681
2682 #if !defined(GEN_Not)
2683 /*-----------------------------------------------------------------*/
2684 /* genNot - generate code for ! operation                          */
2685 /*-----------------------------------------------------------------*/
2686 static void pic16_genNot (iCode *ic)
2687 {
2688   symbol *tlbl;
2689   int size;
2690
2691   FENTRY;
2692   /* assign asmOps to operand & result */
2693   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2694   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2695
2696   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2697   /* if in bit space then a special case */
2698   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2699     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2700       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2701       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2702     } else {
2703       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2705       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2706     }
2707     goto release;
2708   }
2709
2710   size = AOP_SIZE(IC_LEFT(ic));
2711   if(size == 1) {
2712     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2713     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2714     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2715     goto release;
2716   }
2717   pic16_toBoolean(IC_LEFT(ic));
2718
2719   tlbl = newiTempLabel(NULL);
2720   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2721   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2722   pic16_outBitC(IC_RESULT(ic));
2723
2724  release:    
2725   /* release the aops */
2726   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2727   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2728 }
2729 #endif
2730
2731
2732 #if !defined(GEN_Cpl)
2733 /*-----------------------------------------------------------------*/
2734 /* genCpl - generate code for complement                           */
2735 /*-----------------------------------------------------------------*/
2736 static void pic16_genCpl (iCode *ic)
2737 {
2738   int offset = 0;
2739   int size ;
2740
2741     FENTRY;
2742     /* assign asmOps to operand & result */
2743     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2744     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2745
2746     /* if both are in bit space then 
2747     a special case */
2748     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2749         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2750
2751         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2752         pic16_emitcode("cpl","c"); 
2753         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2754         goto release; 
2755     } 
2756
2757     size = AOP_SIZE(IC_RESULT(ic));
2758     while (size--) {
2759 /*
2760         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2761         MOVA(l);       
2762         pic16_emitcode("cpl","a");
2763         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2764 */
2765         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2766               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2767         } else {
2768                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2769                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2770         }
2771         offset++;
2772
2773     }
2774
2775
2776 release:
2777     /* release the aops */
2778     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2779     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2780 }
2781 #endif
2782
2783 /*-----------------------------------------------------------------*/
2784 /* genUminusFloat - unary minus for floating points                */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminusFloat(operand *op,operand *result)
2787 {
2788   int size ,offset =0 ;
2789   
2790     FENTRY;
2791     /* for this we just need to flip the 
2792     first it then copy the rest in place */
2793     size = AOP_SIZE(op);
2794
2795     while(size--) {
2796       pic16_mov2f(AOP(result), AOP(op), offset);
2797       offset++;
2798     }
2799     
2800     /* toggle the MSB's highest bit */
2801     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2802 }
2803
2804 /*-----------------------------------------------------------------*/
2805 /* genUminus - unary minus code generation                         */
2806 /*-----------------------------------------------------------------*/
2807 static void genUminus (iCode *ic)
2808 {
2809   int size, i;
2810   sym_link *optype, *rtype;
2811   symbol *label;
2812   int needLabel=0;
2813
2814     FENTRY;     
2815     
2816     /* assign asmops */
2817     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2818     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2819
2820     /* if both in bit space then special case */
2821     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2822       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2823         
2824         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2825         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2826         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2827         goto release; 
2828     } 
2829
2830     optype = operandType(IC_LEFT(ic));
2831     rtype = operandType(IC_RESULT(ic));
2832
2833     /* if float then do float stuff */
2834     if (IS_FLOAT(optype)) {
2835       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2836       goto release;
2837     }
2838
2839     /* otherwise subtract from zero by taking the 2's complement */
2840     size = AOP_SIZE(IC_LEFT(ic));
2841     label = newiTempLabel ( NULL );
2842     
2843     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2844       for (i=size-1; i > 0; i--) {
2845         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2846       } // for
2847       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2848       for (i=1; i < size; i++) {
2849         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2850         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2851       } // for
2852     } else {
2853       for (i=size-1; i >= 0; i--) {
2854         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2855         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2856       } // for
2857       if (size > 1) {
2858         for (i=0; i < size-2; i++) {
2859           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2860           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2861         } // for
2862         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2863       } // if
2864       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2865     }
2866     if (needLabel)
2867       pic16_emitpLabel (label->key);
2868
2869 release:
2870     /* release the aops */
2871     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2872     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2873 }
2874
2875 #if 0
2876 /*-----------------------------------------------------------------*/
2877 /* saveRegisters - will look for a call and save the registers     */
2878 /*-----------------------------------------------------------------*/
2879 static void saveRegisters(iCode *lic) 
2880 {
2881     int i;
2882     iCode *ic;
2883     bitVect *rsave;
2884     sym_link *dtype;
2885
2886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2887     /* look for call */
2888     for (ic = lic ; ic ; ic = ic->next) 
2889         if (ic->op == CALL || ic->op == PCALL)
2890             break;
2891
2892     if (!ic) {
2893         fprintf(stderr,"found parameter push with no function call\n");
2894         return ;
2895     }
2896
2897     /* if the registers have been saved already then
2898     do nothing */
2899     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2900         return ;
2901
2902     /* find the registers in use at this time 
2903     and push them away to safety */
2904     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2905                           ic->rUsed);
2906
2907     ic->regsSaved = 1;
2908     if (options.useXstack) {
2909         if (bitVectBitValue(rsave,R0_IDX))
2910             pic16_emitcode("mov","b,r0");
2911         pic16_emitcode("mov","r0,%s",spname);
2912         for (i = 0 ; i < pic16_nRegs ; i++) {
2913             if (bitVectBitValue(rsave,i)) {
2914                 if (i == R0_IDX)
2915                     pic16_emitcode("mov","a,b");
2916                 else
2917                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2918                 pic16_emitcode("movx","@r0,a");
2919                 pic16_emitcode("inc","r0");
2920             }
2921         }
2922         pic16_emitcode("mov","%s,r0",spname);
2923         if (bitVectBitValue(rsave,R0_IDX))
2924             pic16_emitcode("mov","r0,b");           
2925     }// else
2926     //for (i = 0 ; i < pic16_nRegs ; i++) {
2927     //    if (bitVectBitValue(rsave,i))
2928     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2929     //}
2930
2931     dtype = operandType(IC_LEFT(ic));
2932     if (currFunc && dtype && 
2933         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2934         IFFUNC_ISISR(currFunc->type) &&
2935         !ic->bankSaved) 
2936
2937         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2938
2939 }
2940 /*-----------------------------------------------------------------*/
2941 /* unsaveRegisters - pop the pushed registers                      */
2942 /*-----------------------------------------------------------------*/
2943 static void unsaveRegisters (iCode *ic)
2944 {
2945     int i;
2946     bitVect *rsave;
2947
2948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2949     /* find the registers in use at this time 
2950     and push them away to safety */
2951     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2952                           ic->rUsed);
2953     
2954     if (options.useXstack) {
2955         pic16_emitcode("mov","r0,%s",spname);   
2956         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2957             if (bitVectBitValue(rsave,i)) {
2958                 pic16_emitcode("dec","r0");
2959                 pic16_emitcode("movx","a,@r0");
2960                 if (i == R0_IDX)
2961                     pic16_emitcode("mov","b,a");
2962                 else
2963                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2964             }       
2965
2966         }
2967         pic16_emitcode("mov","%s,r0",spname);
2968         if (bitVectBitValue(rsave,R0_IDX))
2969             pic16_emitcode("mov","r0,b");
2970     } //else
2971     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2972     //    if (bitVectBitValue(rsave,i))
2973     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2974     //}
2975
2976 }  
2977 #endif
2978
2979 #if 0  // patch 14
2980 /*-----------------------------------------------------------------*/
2981 /* pushSide -                                                      */
2982 /*-----------------------------------------------------------------*/
2983 static void pushSide(operand * oper, int size)
2984 {
2985         int offset = 0;
2986     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2987         while (size--) {
2988                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2989                 if (AOP_TYPE(oper) != AOP_REG &&
2990                     AOP_TYPE(oper) != AOP_DIR &&
2991                     strcmp(l,"a") ) {
2992                         pic16_emitcode("mov","a,%s",l);
2993                         pic16_emitcode("push","acc");
2994                 } else
2995                         pic16_emitcode("push","%s",l);
2996         }
2997 }
2998 #endif // patch 14
2999
3000 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3001 {
3002   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3003     pic16_emitpcode(POC_MOVFW, src);
3004     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3005   } else {
3006     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3007         src, pic16_popGet(AOP(op), offset)));
3008   }
3009 }
3010
3011
3012 /*-----------------------------------------------------------------*/
3013 /* assignResultValue - assign results to oper, rescall==1 is       */
3014 /*                     called from genCall() or genPcall()         */
3015 /*-----------------------------------------------------------------*/
3016 static void assignResultValue(operand * oper, int rescall)
3017 {
3018   int size = AOP_SIZE(oper);
3019   int offset=0;
3020   
3021     FENTRY2;
3022 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3023     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3024
3025     if(rescall) {
3026       /* assign result from a call/pcall function() */
3027                 
3028       /* function results are stored in a special order,
3029        * see top of file with Function return policy, or manual */
3030
3031       if(size <= 4) {
3032         /* 8-bits, result in WREG */
3033         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3034                         
3035         if(size>1) {
3036           /* 16-bits, result in PRODL:WREG */
3037           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3038         }
3039                         
3040         if(size>2) {
3041           /* 24-bits, result in PRODH:PRODL:WREG */
3042           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3043         }
3044                         
3045         if(size>3) {
3046           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3047           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3048         }
3049       
3050       } else {
3051         /* >32-bits, result on stack, and FSR0 points to beginning.
3052          * Fix stack when done */
3053         /* FIXME FIXME */
3054 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3055         while (size--) {
3056 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3057 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3058                 
3059           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3060           GpsuedoStkPtr++;
3061         }
3062                         
3063         /* fix stack */
3064         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3065         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3066         if(STACK_MODEL_LARGE) {
3067           emitSKPNC;
3068           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3069         }
3070       }                 
3071     } else {
3072       int areg = 0;             /* matching argument register */
3073       
3074 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3075       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3076
3077
3078       /* its called from genReceive (probably) -- VR */
3079       /* I hope this code will not be called from somewhere else in the future! 
3080        * We manually set the pseudo stack pointer in genReceive. - dw
3081        */
3082       if(!GpsuedoStkPtr && _G.useWreg) {
3083 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3084
3085         /* The last byte in the assignment is in W */
3086         if(areg <= GpsuedoStkPtr) {
3087           size--;
3088           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3089           offset++;
3090 //          debugf("receive from WREG\n", 0);
3091         }
3092         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3093       }
3094 //      GpsuedoStkPtr++;
3095       _G.stack_lat = AOP_SIZE(oper)-1;
3096
3097       while (size) {
3098         size--;
3099         GpsuedoStkPtr++;
3100         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3101 //        debugf("receive from STACK\n", 0);
3102         offset++;
3103       }
3104     }
3105 }
3106
3107
3108 /*-----------------------------------------------------------------*/
3109 /* genIpush - generate code for pushing this gets a little complex */
3110 /*-----------------------------------------------------------------*/
3111 static void genIpush (iCode *ic)
3112 {
3113 //  int size, offset=0;
3114
3115   FENTRY;
3116   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3117
3118   if(ic->parmPush) {
3119     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3120
3121     /* send to stack as normal */
3122     addSet(&_G.sendSet,ic);
3123 //    addSetHead(&_G.sendSet,ic);
3124     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3125   }
3126
3127         
3128 #if 0
3129     int size, offset = 0 ;
3130     char *l;
3131
3132
3133     /* if this is not a parm push : ie. it is spill push 
3134     and spill push is always done on the local stack */
3135     if (!ic->parmPush) {
3136
3137         /* and the item is spilt then do nothing */
3138         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3139             return ;
3140
3141         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3142         size = AOP_SIZE(IC_LEFT(ic));
3143         /* push it on the stack */
3144         while(size--) {
3145             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3146             if (*l == '#') {
3147                 MOVA(l);
3148                 l = "acc";
3149             }
3150             pic16_emitcode("push","%s",l);
3151         }
3152         return ;        
3153     }
3154
3155     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3156 #endif
3157 }
3158
3159 /*-----------------------------------------------------------------*/
3160 /* genIpop - recover the registers: can happen only for spilling   */
3161 /*-----------------------------------------------------------------*/
3162 static void genIpop (iCode *ic)
3163 {
3164   FENTRY;
3165   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3166 #if 0
3167     int size,offset ;
3168
3169
3170     /* if the temp was not pushed then */
3171     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3172         return ;
3173
3174     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3175     size = AOP_SIZE(IC_LEFT(ic));
3176     offset = (size-1);
3177     while (size--) 
3178         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3179                                    FALSE,TRUE));
3180
3181     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3182 #endif
3183 }
3184
3185 #if 0
3186 /*-----------------------------------------------------------------*/
3187 /* unsaverbank - restores the resgister bank from stack            */
3188 /*-----------------------------------------------------------------*/
3189 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3190 {
3191   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3192 #if 0
3193     int i;
3194     asmop *aop ;
3195     regs *r = NULL;
3196
3197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3198     if (popPsw) {
3199         if (options.useXstack) {
3200             aop = newAsmop(0);
3201             r = getFreePtr(ic,&aop,FALSE);
3202             
3203             
3204             pic16_emitcode("mov","%s,_spx",r->name);
3205             pic16_emitcode("movx","a,@%s",r->name);
3206             pic16_emitcode("mov","psw,a");
3207             pic16_emitcode("dec","%s",r->name);
3208             
3209         }else
3210             pic16_emitcode ("pop","psw");
3211     }
3212
3213     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3214         if (options.useXstack) {       
3215             pic16_emitcode("movx","a,@%s",r->name);
3216             //pic16_emitcode("mov","(%s+%d),a",
3217             //       regspic16[i].base,8*bank+regspic16[i].offset);
3218             pic16_emitcode("dec","%s",r->name);
3219
3220         } else 
3221           pic16_emitcode("pop",""); //"(%s+%d)",
3222         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3223     }
3224
3225     if (options.useXstack) {
3226
3227         pic16_emitcode("mov","_spx,%s",r->name);
3228         pic16_freeAsmop(NULL,aop,ic,TRUE);
3229
3230     }
3231 #endif 
3232 }
3233
3234 /*-----------------------------------------------------------------*/
3235 /* saverbank - saves an entire register bank on the stack          */
3236 /*-----------------------------------------------------------------*/
3237 static void saverbank (int bank, iCode *ic, bool pushPsw)
3238 {
3239   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3240 #if 0
3241     int i;
3242     asmop *aop ;
3243     regs *r = NULL;
3244
3245     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3246     if (options.useXstack) {
3247
3248         aop = newAsmop(0);
3249         r = getFreePtr(ic,&aop,FALSE);  
3250         pic16_emitcode("mov","%s,_spx",r->name);
3251
3252     }
3253
3254     for (i = 0 ; i < pic16_nRegs ;i++) {
3255         if (options.useXstack) {
3256             pic16_emitcode("inc","%s",r->name);
3257             //pic16_emitcode("mov","a,(%s+%d)",
3258             //         regspic16[i].base,8*bank+regspic16[i].offset);
3259             pic16_emitcode("movx","@%s,a",r->name);           
3260         } else 
3261           pic16_emitcode("push","");// "(%s+%d)",
3262                      //regspic16[i].base,8*bank+regspic16[i].offset);
3263     }
3264     
3265     if (pushPsw) {
3266         if (options.useXstack) {
3267             pic16_emitcode("mov","a,psw");
3268             pic16_emitcode("movx","@%s,a",r->name);     
3269             pic16_emitcode("inc","%s",r->name);
3270             pic16_emitcode("mov","_spx,%s",r->name);       
3271             pic16_freeAsmop (NULL,aop,ic,TRUE);
3272             
3273         } else
3274             pic16_emitcode("push","psw");
3275         
3276         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3277     }
3278     ic->bankSaved = 1;
3279 #endif
3280 }
3281 #endif  /* 0 */
3282
3283
3284 static int wparamCmp(void *p1, void *p2)
3285 {
3286   return (!strcmp((char *)p1, (char *)p2));
3287 }
3288
3289 int inWparamList(char *s)
3290 {
3291   return isinSetWith(wparamList, s, wparamCmp);
3292
3293
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genCall - generates a call statement                            */
3297 /*-----------------------------------------------------------------*/
3298 static void genCall (iCode *ic)
3299 {
3300   sym_link *ftype;   
3301   int stackParms=0;
3302   int use_wreg=0;
3303   int inwparam=0;
3304   char *fname;
3305   
3306     FENTRY;
3307
3308     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3309     /* if caller saves & we have not saved then */
3310 //    if (!ic->regsSaved)
3311 //      saveRegisters(ic);
3312
3313         /* initialise stackParms for IPUSH pushes */
3314 //      stackParms = psuedoStkPtr;
3315 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3316     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3317     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3318
3319 #if 0
3320     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3321 #endif
3322
3323     /* if send set is not empty the assign */
3324     if (_G.sendSet) {
3325       iCode *sic;
3326       int psuedoStkPtr=-1; 
3327       int firstTimeThruLoop = 1;
3328
3329
3330         /* reverse sendSet if function is not reentrant */
3331         if(!IFFUNC_ISREENT(ftype))
3332           _G.sendSet = reverseSet(_G.sendSet);
3333
3334         /* First figure how many parameters are getting passed */
3335         stackParms = 0;
3336         use_wreg = 0;
3337         
3338         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3339           int size;
3340 //          int offset = 0;
3341
3342             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3343             size = AOP_SIZE(IC_LEFT(sic));
3344
3345             stackParms += size;
3346
3347             /* pass the last byte through WREG */
3348             if(inwparam) {
3349
3350               while (size--) {
3351                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3354
3355                 if(!firstTimeThruLoop) {
3356                   /* If this is not the first time we've been through the loop
3357                    * then we need to save the parameter in a temporary
3358                    * register. The last byte of the last parameter is
3359                    * passed in W. */
3360
3361                   pushw();
3362 //                  --psuedoStkPtr;             // sanity check
3363                   use_wreg = 1;
3364                 }
3365                 
3366                 firstTimeThruLoop=0;
3367
3368                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3369
3370 //                offset++;
3371               }
3372             } else {
3373               /* all arguments are passed via stack */
3374               use_wreg = 0;
3375
3376               while (size--) {
3377                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3378                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3379                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3380
3381 //                pushaop(AOP(IC_LEFT(sic)), size);
3382                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3383
3384                 if(!_G.resDirect)
3385                   pushw();
3386               }
3387             }
3388
3389             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3390           }
3391
3392           if(inwparam) {
3393             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3394               pushw();  /* save last parameter to stack if functions has varargs */
3395               use_wreg = 0;
3396             } else
3397               use_wreg = 1;
3398           } else use_wreg = 0;
3399
3400           _G.stackRegSet = _G.sendSet;
3401           _G.sendSet = NULL;
3402     }
3403
3404     /* make the call */
3405     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3406
3407     GpsuedoStkPtr=0;
3408     
3409     /* if we need to assign a result value */
3410     if ((IS_ITEMP(IC_RESULT(ic))
3411           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3412               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3413         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3414
3415       _G.accInUse++;
3416       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3417       _G.accInUse--;
3418
3419       assignResultValue(IC_RESULT(ic), 1);
3420
3421       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3422                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3423                 
3424       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3425     }
3426
3427     if(!stackParms && ic->parmBytes) {
3428       stackParms = ic->parmBytes;
3429     }
3430       
3431     stackParms -= use_wreg;
3432     
3433     if(stackParms>0) {
3434       if(stackParms == 1) {
3435         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3436       } else {
3437         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3438         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3439       }
3440       if(STACK_MODEL_LARGE) {
3441         emitSKPNC;
3442         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3443       }
3444     }
3445
3446 #if 0
3447     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3448 #endif
3449
3450     /* adjust the stack for parameters if required */
3451 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3452
3453 #if 0
3454       /* if register bank was saved then pop them */
3455       if (ic->bankSaved)
3456         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3457
3458       /* if we hade saved some registers then unsave them */
3459       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3460         unsaveRegisters (ic);
3461 #endif
3462 }
3463
3464
3465
3466 /*-----------------------------------------------------------------*/
3467 /* genPcall - generates a call by pointer statement                */
3468 /*            new version, created from genCall - HJD              */
3469 /*-----------------------------------------------------------------*/
3470 static void genPcall (iCode *ic)
3471 {
3472   sym_link *ftype, *fntype;
3473   int stackParms=0;
3474   symbol *retlbl = newiTempLabel(NULL);
3475   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3476   
3477     FENTRY;
3478
3479     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3480     fntype = operandType( IC_LEFT(ic) )->next;
3481
3482     /* if send set is not empty the assign */
3483     if (_G.sendSet) {
3484       iCode *sic;
3485       int psuedoStkPtr=-1; 
3486
3487       /* reverse sendSet if function is not reentrant */
3488       if(!IFFUNC_ISREENT(fntype))
3489         _G.sendSet = reverseSet(_G.sendSet);
3490
3491       stackParms = 0;
3492       
3493       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3494         int size;
3495
3496           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3497           size = AOP_SIZE(IC_LEFT(sic));
3498           stackParms += size;
3499
3500           /* all parameters are passed via stack, since WREG is clobbered
3501            * by the calling sequence */
3502           while (size--) {
3503             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3504             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3505             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3506
3507             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3508             pushw();
3509           }
3510
3511           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3512       }
3513
3514       _G.stackRegSet = _G.sendSet;
3515       _G.sendSet = NULL;
3516     }
3517
3518     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3519
3520     // push return address
3521     // push $ on return stack, then replace with retlbl
3522
3523     /* Thanks to Thorsten Klose for pointing out that the following
3524      * snippet should be interrupt safe */
3525     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3526     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3527
3528     pic16_emitpcodeNULLop(POC_PUSH);
3529
3530     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3532     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3534     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3535     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3536
3537
3538     /* restore interrupt control register */
3539     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3540     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3541
3542     /* make the call by writing the pointer into pc */
3543     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3544     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3545
3546     // note: MOVFF to PCL not allowed
3547     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3548     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3549
3550
3551     /* return address is here: (X) */
3552     pic16_emitpLabelFORCE(retlbl->key);
3553
3554     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3555
3556     GpsuedoStkPtr=0;
3557     /* if we need assign a result value */
3558     if ((IS_ITEMP(IC_RESULT(ic))
3559           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3560               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3561         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3562
3563       _G.accInUse++;
3564       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3565       _G.accInUse--;
3566
3567       assignResultValue(IC_RESULT(ic), 1);
3568
3569       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3570               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3571                 
3572       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3573     }
3574
3575 //    stackParms -= use_wreg;
3576     
3577     if(stackParms>0) {
3578       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3579       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3580       if(STACK_MODEL_LARGE) {
3581         emitSKPNC;
3582         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3583       }
3584     }
3585 }
3586
3587 /*-----------------------------------------------------------------*/
3588 /* resultRemat - result  is rematerializable                       */
3589 /*-----------------------------------------------------------------*/
3590 static int resultRemat (iCode *ic)
3591 {
3592   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3593   if (SKIP_IC(ic) || ic->op == IFX)
3594     return 0;
3595
3596   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3597     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3598     if (sym->remat && !POINTER_SET(ic)) 
3599       return 1;
3600   }
3601
3602   return 0;
3603 }
3604
3605 #if defined(__BORLANDC__) || defined(_MSC_VER)
3606 #define STRCASECMP stricmp
3607 #else
3608 #define STRCASECMP strcasecmp
3609 #endif
3610
3611 #if 0
3612 /*-----------------------------------------------------------------*/
3613 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3614 /*-----------------------------------------------------------------*/
3615 static bool inExcludeList(char *s)
3616 {
3617   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3618     int i =0;
3619     
3620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3621     if (options.excludeRegs[i] &&
3622     STRCASECMP(options.excludeRegs[i],"none") == 0)
3623         return FALSE ;
3624
3625     for ( i = 0 ; options.excludeRegs[i]; i++) {
3626         if (options.excludeRegs[i] &&
3627         STRCASECMP(s,options.excludeRegs[i]) == 0)
3628             return TRUE;
3629     }
3630     return FALSE ;
3631 }
3632 #endif
3633
3634 /*-----------------------------------------------------------------*/
3635 /* genFunction - generated code for function entry                 */
3636 /*-----------------------------------------------------------------*/
3637 static void genFunction (iCode *ic)
3638 {
3639   symbol *sym;
3640   sym_link *ftype;
3641   
3642     FENTRY;
3643     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3644
3645     pic16_labelOffset += (max_key+4);
3646     max_key=0;
3647     GpsuedoStkPtr=0;
3648     _G.nRegsSaved = 0;
3649         
3650     ftype = operandType(IC_LEFT(ic));
3651     sym = OP_SYMBOL(IC_LEFT(ic));
3652
3653     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3654       /* create an absolute section at the interrupt vector:
3655        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3656       symbol *asym;
3657       char asymname[128];
3658       pBlock *apb;
3659
3660 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3661
3662         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3663           sprintf(asymname, "ivec_%s", sym->name);
3664         else
3665           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3666   
3667         /* when an interrupt is declared as naked, do not emit the special
3668          * wrapper segment at vector address. The user should take care for
3669          * this instead. -- VR */
3670
3671         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3672           asym = newSymbol(asymname, 0);
3673           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3674           pic16_addpBlock( apb );
3675
3676           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3677           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3678           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3679           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3680           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3681                 
3682           /* mark the end of this tiny function */
3683           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3684         } else {
3685           sprintf(asymname, "%s", sym->rname);
3686         }
3687
3688         {
3689           absSym *abSym;
3690
3691             abSym = Safe_calloc(1, sizeof(absSym));
3692             strcpy(abSym->name, asymname);
3693
3694             switch( FUNC_INTNO(sym->type) ) {
3695               case 0: abSym->address = 0x000000; break;
3696               case 1: abSym->address = 0x000008; break;
3697               case 2: abSym->address = 0x000018; break;
3698               
3699               default:
3700 //                fprintf(stderr, "no interrupt number is given\n");
3701                 abSym->address = -1; break;
3702             }
3703
3704             /* relocate interrupt vectors if needed */
3705             if(abSym->address != -1)
3706               abSym->address += pic16_options.ivt_loc;
3707
3708             addSet(&absSymSet, abSym);
3709         }
3710     }
3711
3712     /* create the function header */
3713     pic16_emitcode(";","-----------------------------------------");
3714     pic16_emitcode(";"," function %s",sym->name);
3715     pic16_emitcode(";","-----------------------------------------");
3716
3717     pic16_emitcode("","%s:",sym->rname);
3718     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3719
3720     {
3721       absSym *ab;
3722
3723         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3724           if(!strcmp(ab->name, sym->rname)) {
3725             pic16_pBlockConvert2Absolute(pb);
3726             break;
3727           }
3728         }
3729     }
3730
3731     if(IFFUNC_ISNAKED(ftype)) {
3732       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3733       return;
3734     }
3735         
3736     /* if critical function then turn interrupts off */
3737     if (IFFUNC_ISCRITICAL(ftype)) {
3738       //pic16_emitcode("clr","ea");
3739     }
3740
3741     currFunc = sym;             /* update the currFunc symbol */
3742     _G.fregsUsed = sym->regsUsed;
3743     _G.sregsAlloc = newBitVect(128);
3744     
3745
3746     /* if this is an interrupt service routine then
3747      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3748     if (IFFUNC_ISISR(sym->type)) {
3749         _G.usefastretfie = 1;   /* use shadow registers by default */
3750         
3751         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3752         if(!FUNC_ISSHADOWREGS(sym->type)) {
3753           /* do not save WREG,STATUS,BSR for high priority interrupts
3754            * because they are stored in the hardware shadow registers already */
3755           _G.usefastretfie = 0;
3756           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3757           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3758           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3759         }
3760
3761         /* these should really be optimized somehow, because not all
3762          * interrupt handlers modify them */
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3764         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3765         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3766         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3767         
3768 //        pic16_pBlockConvert2ISR(pb);
3769     }
3770
3771     /* emit code to setup stack frame if user enabled,
3772      * and function is not main() */
3773     
3774 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3775     if(strcmp(sym->name, "main")) {
3776       if(0 
3777         || !options.ommitFramePtr 
3778 //        || sym->regsUsed
3779         || IFFUNC_ARGS(sym->type)
3780         || FUNC_HASSTACKPARM(sym->etype)
3781         ) {
3782         /* setup the stack frame */
3783         if(STACK_MODEL_LARGE)
3784           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3785         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3786
3787         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3788         if(STACK_MODEL_LARGE)
3789           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790       }
3791     }
3792
3793     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3794           && sym->stack) {
3795
3796       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3797
3798       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3799       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3800       emitSKPC;
3801       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3802     }
3803           
3804     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3805       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3806         _G.useWreg = 0;
3807       else
3808         _G.useWreg = 1;
3809     } else
3810       _G.useWreg = 0;
3811
3812     /* if callee-save to be used for this function
3813      * then save the registers being used in this function */
3814 //    if (IFFUNC_CALLEESAVES(sym->type))
3815     {
3816       int i;
3817
3818         /* if any registers used */
3819         if (sym->regsUsed) {
3820           /* save the registers used */
3821           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3822           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3823           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3824             if (bitVectBitValue(sym->regsUsed,i)) {
3825               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3826               _G.nRegsSaved++;
3827
3828               if(!pic16_regWithIdx(i)->wasUsed) {
3829                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3830                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831                 pic16_regWithIdx(i)->wasUsed = 1;
3832               }
3833             }
3834           }
3835           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3836         }
3837     }
3838         
3839     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3840 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3841 }
3842
3843 /*-----------------------------------------------------------------*/
3844 /* genEndFunction - generates epilogue for functions               */
3845 /*-----------------------------------------------------------------*/
3846 static void genEndFunction (iCode *ic)
3847 {
3848   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3849
3850     FENTRY;
3851
3852     if(IFFUNC_ISNAKED(sym->type)) {
3853       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3854       return;
3855     }
3856
3857     _G.stack_lat = 0;
3858
3859     /* add code for ISCRITICAL */
3860     if(IFFUNC_ISCRITICAL(sym->type)) {
3861       /* if critical function, turn on interrupts */
3862       
3863       /* TODO: add code here -- VR */
3864     }
3865     
3866 //    sym->regsUsed = _G.fregsUsed;
3867     
3868     /* now we need to restore the registers */
3869     /* if any registers used */
3870
3871     /* first restore registers that might be used for stack access */
3872     if(_G.sregsAllocSet) {
3873     regs *sr;
3874     
3875       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3876       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3877         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3878       }
3879     }
3880
3881     if (sym->regsUsed) {
3882       int i;
3883
3884         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3885         /* restore registers used */
3886         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3887         for ( i = sym->regsUsed->size; i >= 0; i--) {
3888           if (bitVectBitValue(sym->regsUsed,i)) {
3889             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3890             _G.nRegsSaved--;
3891           }
3892         }
3893         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3894     }
3895
3896       
3897
3898     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3899           && sym->stack) {
3900       if (sym->stack == 1) {
3901         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3902         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903       } else {
3904         // we have to add more than one...
3905         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3906         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3907         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3908         emitSKPNC;
3909         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3910         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3911         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3912       }
3913     }
3914
3915     if(strcmp(sym->name, "main")) {
3916       if(0
3917         || !options.ommitFramePtr
3918 //        || sym->regsUsed
3919         || IFFUNC_ARGS(sym->type)
3920         || FUNC_HASSTACKPARM(sym->etype)
3921         ) {
3922         /* restore stack frame */
3923         if(STACK_MODEL_LARGE)
3924           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3925         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3926       }
3927     }
3928
3929     _G.useWreg = 0;
3930
3931     if (IFFUNC_ISISR(sym->type)) {
3932       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3933       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3934       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3935       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3936
3937       if(!FUNC_ISSHADOWREGS(sym->type)) {
3938         /* do not restore interrupt vector for WREG,STATUS,BSR
3939          * for high priority interrupt, see genFunction */
3940         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3941         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3942         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3943       }
3944 //      _G.interruptvector = 0;         /* sanity check */
3945
3946
3947       /* if debug then send end of function */
3948 /*      if (options.debug && currFunc)  */
3949       if (currFunc) {
3950         debugFile->writeEndFunction (currFunc, ic, 1);
3951       }
3952         
3953       if(_G.usefastretfie)
3954         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3955       else
3956         pic16_emitpcodeNULLop(POC_RETFIE);
3957
3958       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3959       
3960       _G.usefastretfie = 0;
3961       return;
3962     }
3963
3964     if (IFFUNC_ISCRITICAL(sym->type)) {
3965       pic16_emitcode("setb","ea");
3966     }
3967
3968     /* if debug then send end of function */
3969     if (currFunc) {
3970       debugFile->writeEndFunction (currFunc, ic, 1);
3971     }
3972
3973     /* insert code to restore stack frame, if user enabled it
3974      * and function is not main() */
3975          
3976
3977     pic16_emitpcodeNULLop(POC_RETURN);
3978
3979     /* Mark the end of a function */
3980     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3981 }
3982
3983
3984 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3985 {
3986   unsigned long lit=1;
3987   operand *op;
3988
3989     op = IC_LEFT(ic);
3990   
3991     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3992     if(AOP_TYPE(op) == AOP_LIT) {
3993       if(!IS_FLOAT(operandType( op ))) {
3994         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3995       } else {
3996         union {
3997           unsigned long lit_int;
3998           float lit_float;
3999         } info;
4000         
4001         /* take care if literal is a float */
4002         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4003         lit = info.lit_int;
4004       }
4005     }
4006
4007     if(is_LitOp(op)) {
4008       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4009         pic16_emitpcode(POC_CLRF, dest);
4010       } else {
4011         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4012         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4013       }
4014     } else {
4015       if(dest->type == PO_WREG && (offset == 0)) {
4016         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4017       return;
4018     }
4019     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4020   }
4021 }
4022
4023 /*-----------------------------------------------------------------*/
4024 /* genRet - generate code for return statement                     */
4025 /*-----------------------------------------------------------------*/
4026 static void genRet (iCode *ic)
4027 {
4028   int size;
4029   operand *left;
4030
4031     FENTRY;
4032         /* if we have no return value then
4033          * just generate the "ret" */
4034         
4035         if (!IC_LEFT(ic)) 
4036                 goto jumpret;       
4037     
4038         /* we have something to return then
4039          * move the return value into place */
4040         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4041         size = AOP_SIZE(IC_LEFT(ic));
4042
4043         if(size <= 4) {
4044           if(size>3)
4045             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4046           
4047           if(size>2)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4049
4050           if(size>1)
4051             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4052           
4053           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4054
4055         } else {
4056                 /* >32-bits, setup stack and FSR0 */
4057                 while (size--) {
4058 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4059 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4060
4061                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4062
4063 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4064                         GpsuedoStkPtr++;
4065                 }
4066                         
4067                 /* setup FSR0 */
4068                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4069                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4070
4071                 if(STACK_MODEL_LARGE) {
4072                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4074                 } else {
4075                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4076                 }
4077         }
4078                                 
4079 #if 0
4080         /* old code, left here for reference -- VR */    
4081         while (size--) {
4082           char *l ;
4083
4084                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4085                         /* #NOCHANGE */
4086                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4087                         pic16_emitpcomment("push %s",l);
4088                         pushed++;
4089                 } else {
4090                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4091                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4092                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4093                         
4094                         if (strcmp(fReturn[offset],l)) {
4095                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4096                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4097                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4098                                 } else {
4099                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4100                                 }
4101                                 
4102                                 if(size) {
4103                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4104                                 }
4105                                 offset++;
4106                         }
4107                 }
4108         }    
4109
4110         if (pushed) {
4111                 while(pushed) {
4112                         pushed--;
4113                         if (strcmp(fReturn[pushed],"a"))
4114                                 pic16_emitcode("pop",fReturn[pushed]);
4115                         else
4116                                 pic16_emitcode("pop","acc");
4117                 }
4118         }
4119 #endif
4120
4121
4122         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4123     
4124 jumpret:
4125         /* generate a jump to the return label
4126          * if the next is not the return statement */
4127         if (!(ic->next && ic->next->op == LABEL
4128                 && IC_LABEL(ic->next) == returnLabel)) {
4129         
4130                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4131                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4132         }
4133 }
4134
4135 /*-----------------------------------------------------------------*/
4136 /* genLabel - generates a label                                    */
4137 /*-----------------------------------------------------------------*/
4138 static void genLabel (iCode *ic)
4139 {
4140   FENTRY;
4141
4142   /* special case never generate */
4143   if (IC_LABEL(ic) == entryLabel)
4144     return ;
4145
4146   pic16_emitpLabel(IC_LABEL(ic)->key);
4147 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genGoto - generates a goto                                      */
4152 /*-----------------------------------------------------------------*/
4153 //tsd
4154 static void genGoto (iCode *ic)
4155 {
4156   FENTRY;
4157   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4158 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4159 }
4160
4161
4162 /*-----------------------------------------------------------------*/
4163 /* genMultbits :- multiplication of bits                           */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultbits (operand *left, 
4166                          operand *right, 
4167                          operand *result)
4168 {
4169   FENTRY;
4170
4171   if(!pic16_sameRegs(AOP(result),AOP(right)))
4172     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4173
4174   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4175   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4176   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4177
4178 }
4179
4180
4181 /*-----------------------------------------------------------------*/
4182 /* genMultOneByte : 8 bit multiplication & division                */
4183 /*-----------------------------------------------------------------*/
4184 static void genMultOneByte (operand *left,
4185                             operand *right,
4186                             operand *result)
4187 {
4188
4189   FENTRY;
4190   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4192
4193   /* (if two literals, the value is computed before) */
4194   /* if one literal, literal on the right */
4195   if (AOP_TYPE(left) == AOP_LIT){
4196     operand *t = right;
4197     right = left;
4198     left = t;
4199   }
4200
4201         /* size is already checked in genMult == 1 */
4202 //      size = AOP_SIZE(result);
4203
4204         if (AOP_TYPE(right) == AOP_LIT){
4205                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4206                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4207                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4208                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4209         } else {
4210                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4211                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4212                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4213                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214         }
4215         
4216         pic16_genMult8X8_8 (left, right,result);
4217 }
4218
4219 /*-----------------------------------------------------------------*/
4220 /* genMultOneWord : 16 bit multiplication                          */
4221 /*-----------------------------------------------------------------*/
4222 static void genMultOneWord (operand *left,
4223                             operand *right,
4224                             operand *result)
4225 {
4226   FENTRY;
4227   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4228   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4229
4230   /* (if two literals, the value is computed before)
4231    * if one literal, literal on the right */
4232   if (AOP_TYPE(left) == AOP_LIT){
4233     operand *t = right;
4234     right = left;
4235     left = t;
4236   }
4237
4238   /* size is checked already == 2 */
4239 //  size = AOP_SIZE(result);
4240
4241   if (AOP_TYPE(right) == AOP_LIT) {
4242     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4243       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4244       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4245       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4246   } else {
4247     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4248       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4249       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4250       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4251   }
4252         
4253   pic16_genMult16X16_16(left, right,result);
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* genMultOneLong : 32 bit multiplication                          */
4258 /*-----------------------------------------------------------------*/
4259 static void genMultOneLong (operand *left,
4260                             operand *right,
4261                             operand *result)
4262 {
4263   FENTRY;
4264   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4265   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4266
4267   /* (if two literals, the value is computed before)
4268    * if one literal, literal on the right */
4269   if (AOP_TYPE(left) == AOP_LIT){
4270     operand *t = right;
4271     right = left;
4272     left = t;
4273   }
4274
4275   /* size is checked already == 4 */
4276 //  size = AOP_SIZE(result);
4277
4278   if (AOP_TYPE(right) == AOP_LIT) {
4279     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4280         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4281         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4282         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4283   } else {
4284     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4285         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4286         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4287         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4288   }
4289         
4290   pic16_genMult32X32_32(left, right,result);
4291 }
4292
4293
4294
4295 /*-----------------------------------------------------------------*/
4296 /* genMult - generates code for multiplication                     */
4297 /*-----------------------------------------------------------------*/
4298 static void genMult (iCode *ic)
4299 {
4300   operand *left = IC_LEFT(ic);
4301   operand *right = IC_RIGHT(ic);
4302   operand *result= IC_RESULT(ic);   
4303
4304     FENTRY;
4305         /* assign the amsops */
4306         pic16_aopOp (left,ic,FALSE);
4307         pic16_aopOp (right,ic,FALSE);
4308         pic16_aopOp (result,ic,TRUE);
4309
4310         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4311
4312         /* special cases first *
4313         * both are bits */
4314         if (AOP_TYPE(left) == AOP_CRY
4315                 && AOP_TYPE(right)== AOP_CRY) {
4316                 genMultbits(left,right,result);
4317           goto release ;
4318         }
4319
4320         /* if both are of size == 1 */
4321         if(AOP_SIZE(left) == 1
4322                 && AOP_SIZE(right) == 1) {
4323                 genMultOneByte(left,right,result);
4324           goto release ;
4325         }
4326
4327         /* if both are of size == 2 */
4328         if(AOP_SIZE(left) == 2
4329                 && AOP_SIZE(right) == 2) {
4330                 genMultOneWord(left, right, result);
4331           goto release;
4332         }
4333         
4334         /* if both are of size == 4 */
4335         if(AOP_SIZE(left) == 4
4336                 && AOP_SIZE(right) == 4) {
4337                 genMultOneLong(left, right, result);
4338           goto release;
4339         }
4340         
4341         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4342
4343
4344         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4345         /* should have been converted to function call */
4346         assert(0) ;
4347
4348 release :
4349         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351         pic16_freeAsmop(result,NULL,ic,TRUE); 
4352 }
4353
4354 /*-----------------------------------------------------------------*/
4355 /* genDivbits :- division of bits                                  */
4356 /*-----------------------------------------------------------------*/
4357 static void genDivbits (operand *left, 
4358                         operand *right, 
4359                         operand *result)
4360 {
4361   char *l;
4362
4363     FENTRY;
4364     /* the result must be bit */    
4365     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4367
4368     MOVA(l);    
4369
4370     pic16_emitcode("div","ab");
4371     pic16_emitcode("rrc","a");
4372     pic16_aopPut(AOP(result),"c",0);
4373 }
4374
4375 /*-----------------------------------------------------------------*/
4376 /* genDivOneByte : 8 bit division                                  */
4377 /*-----------------------------------------------------------------*/
4378 static void genDivOneByte (operand *left,
4379                            operand *right,
4380                            operand *result)
4381 {
4382   sym_link *opetype = operandType(result);
4383   char *l ;
4384   symbol *lbl ;
4385   int size,offset;
4386
4387         /* result = divident / divisor
4388          * - divident may be a register or a literal,
4389          * - divisor may be a register or a literal,
4390          * so there are 3 cases (literal / literal is optimized
4391          * by the front-end) to handle.
4392          * In addition we must handle signed and unsigned, which
4393          * result in 6 final different cases -- VR */
4394
4395     FENTRY;
4396     
4397     size = AOP_SIZE(result) - 1;
4398     offset = 1;
4399     /* signed or unsigned */
4400     if (SPEC_USIGN(opetype)) {
4401       pCodeOp *pct1,    /* count */
4402                 *pct2,  /* reste */
4403                 *pct3;  /* temp */
4404       symbol *label1, *label2, *label3;;
4405
4406
4407         /* unsigned is easy */
4408
4409         pct1 = pic16_popGetTempReg(1);
4410         pct2 = pic16_popGetTempReg(1);
4411         pct3 = pic16_popGetTempReg(1);
4412         
4413         label1 = newiTempLabel(NULL);
4414         label2 = newiTempLabel(NULL);
4415         label3 = newiTempLabel(NULL);
4416
4417         /* the following algorithm is extracted from divuint.c */
4418
4419         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4420         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4421         
4422         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4423
4424         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4425         
4426         pic16_emitpLabel(label1->key);
4427         
4428         emitCLRC;
4429         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4430
4431
4432         emitCLRC;
4433         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4434         
4435
4436         emitSKPNC;
4437         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4438         
4439         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4440         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4441         
4442         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4443         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4444         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4445         
4446         pic16_emitpLabel( label3->key );
4447         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4448         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4449         
4450         
4451
4452         pic16_emitpLabel(label2->key);
4453         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4454         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4455         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4456         
4457         /* result is in wreg */
4458         if(AOP_TYPE(result) != AOP_ACC)
4459                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4460
4461         pic16_popReleaseTempReg( pct3, 1);
4462         pic16_popReleaseTempReg( pct2, 1);
4463         pic16_popReleaseTempReg( pct1, 1);
4464
4465         return ;
4466     }
4467
4468     /* signed is a little bit more difficult */
4469
4470     /* save the signs of the operands */
4471     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4472     MOVA(l);    
4473     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4474     pic16_emitcode("push","acc"); /* save it on the stack */
4475
4476     /* now sign adjust for both left & right */
4477     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4478     MOVA(l);       
4479     lbl = newiTempLabel(NULL);
4480     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4481     pic16_emitcode("cpl","a");   
4482     pic16_emitcode("inc","a");
4483     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4484     pic16_emitcode("mov","b,a");
4485
4486     /* sign adjust left side */
4487     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4488     MOVA(l);
4489
4490     lbl = newiTempLabel(NULL);
4491     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4492     pic16_emitcode("cpl","a");
4493     pic16_emitcode("inc","a");
4494     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4495
4496     /* now the division */
4497     pic16_emitcode("div","ab");
4498     /* we are interested in the lower order
4499     only */
4500     pic16_emitcode("mov","b,a");
4501     lbl = newiTempLabel(NULL);
4502     pic16_emitcode("pop","acc");   
4503     /* if there was an over flow we don't 
4504     adjust the sign of the result */
4505     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4506     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4507     CLRC;
4508     pic16_emitcode("clr","a");
4509     pic16_emitcode("subb","a,b");
4510     pic16_emitcode("mov","b,a");
4511     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512
4513     /* now we are done */
4514     pic16_aopPut(AOP(result),"b",0);
4515     if(size > 0){
4516         pic16_emitcode("mov","c,b.7");
4517         pic16_emitcode("subb","a,acc");   
4518     }
4519     while (size--)
4520         pic16_aopPut(AOP(result),"a",offset++);
4521
4522 }
4523
4524 /*-----------------------------------------------------------------*/
4525 /* genDiv - generates code for division                            */
4526 /*-----------------------------------------------------------------*/
4527 static void genDiv (iCode *ic)
4528 {
4529     operand *left = IC_LEFT(ic);
4530     operand *right = IC_RIGHT(ic);
4531     operand *result= IC_RESULT(ic);   
4532
4533
4534         /* Division is a very lengthy algorithm, so it is better
4535          * to call support routines than inlining algorithm.
4536          * Division functions written here just in case someone
4537          * wants to inline and not use the support libraries -- VR */
4538
4539     FENTRY;
4540     
4541     /* assign the amsops */
4542     pic16_aopOp (left,ic,FALSE);
4543     pic16_aopOp (right,ic,FALSE);
4544     pic16_aopOp (result,ic,TRUE);
4545
4546     /* special cases first */
4547     /* both are bits */
4548     if (AOP_TYPE(left) == AOP_CRY &&
4549         AOP_TYPE(right)== AOP_CRY) {
4550         genDivbits(left,right,result);
4551         goto release ;
4552     }
4553
4554     /* if both are of size == 1 */
4555     if (AOP_SIZE(left) == 1 &&
4556         AOP_SIZE(right) == 1 ) {
4557         genDivOneByte(left,right,result);
4558         goto release ;
4559     }
4560
4561     /* should have been converted to function call */
4562     assert(0);
4563 release :
4564     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566     pic16_freeAsmop(result,NULL,ic,TRUE); 
4567 }
4568
4569 /*-----------------------------------------------------------------*/
4570 /* genModbits :- modulus of bits                                   */
4571 /*-----------------------------------------------------------------*/
4572 static void genModbits (operand *left, 
4573                         operand *right, 
4574                         operand *result)
4575 {
4576   char *l;
4577
4578     FENTRY;  
4579     
4580     werror(W_POSSBUG2, __FILE__, __LINE__);
4581     /* the result must be bit */    
4582     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4583     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4584
4585     MOVA(l);       
4586
4587     pic16_emitcode("div","ab");
4588     pic16_emitcode("mov","a,b");
4589     pic16_emitcode("rrc","a");
4590     pic16_aopPut(AOP(result),"c",0);
4591 }
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genModOneByte : 8 bit modulus                                   */
4595 /*-----------------------------------------------------------------*/
4596 static void genModOneByte (operand *left,
4597                            operand *right,
4598                            operand *result)
4599 {
4600   sym_link *opetype = operandType(result);
4601   char *l ;
4602   symbol *lbl ;
4603
4604     FENTRY;
4605     werror(W_POSSBUG2, __FILE__, __LINE__);
4606
4607     /* signed or unsigned */
4608     if (SPEC_USIGN(opetype)) {
4609         /* unsigned is easy */
4610         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4611         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4612         MOVA(l);    
4613         pic16_emitcode("div","ab");
4614         pic16_aopPut(AOP(result),"b",0);
4615         return ;
4616     }
4617
4618     /* signed is a little bit more difficult */
4619
4620     /* save the signs of the operands */
4621     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4622     MOVA(l);
4623
4624     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4625     pic16_emitcode("push","acc"); /* save it on the stack */
4626
4627     /* now sign adjust for both left & right */
4628     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4629     MOVA(l);
4630
4631     lbl = newiTempLabel(NULL);
4632     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4633     pic16_emitcode("cpl","a");   
4634     pic16_emitcode("inc","a");
4635     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4636     pic16_emitcode("mov","b,a"); 
4637
4638     /* sign adjust left side */
4639     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4640     MOVA(l);
4641
4642     lbl = newiTempLabel(NULL);
4643     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4644     pic16_emitcode("cpl","a");   
4645     pic16_emitcode("inc","a");
4646     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4647
4648     /* now the multiplication */
4649     pic16_emitcode("div","ab");
4650     /* we are interested in the lower order
4651     only */
4652     lbl = newiTempLabel(NULL);
4653     pic16_emitcode("pop","acc");   
4654     /* if there was an over flow we don't 
4655     adjust the sign of the result */
4656     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4657     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4658     CLRC ;
4659     pic16_emitcode("clr","a");
4660     pic16_emitcode("subb","a,b");
4661     pic16_emitcode("mov","b,a");
4662     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4663
4664     /* now we are done */
4665     pic16_aopPut(AOP(result),"b",0);
4666
4667 }
4668
4669 /*-----------------------------------------------------------------*/
4670 /* genMod - generates code for division                            */
4671 /*-----------------------------------------------------------------*/
4672 static void genMod (iCode *ic)
4673 {
4674   operand *left = IC_LEFT(ic);
4675   operand *right = IC_RIGHT(ic);
4676   operand *result= IC_RESULT(ic);  
4677
4678     FENTRY;
4679     
4680     /* assign the amsops */
4681     pic16_aopOp (left,ic,FALSE);
4682     pic16_aopOp (right,ic,FALSE);
4683     pic16_aopOp (result,ic,TRUE);
4684
4685     /* special cases first */
4686     /* both are bits */
4687     if (AOP_TYPE(left) == AOP_CRY &&
4688         AOP_TYPE(right)== AOP_CRY) {
4689         genModbits(left,right,result);
4690         goto release ;
4691     }
4692
4693     /* if both are of size == 1 */
4694     if (AOP_SIZE(left) == 1 &&
4695         AOP_SIZE(right) == 1 ) {
4696         genModOneByte(left,right,result);
4697         goto release ;
4698     }
4699
4700     /* should have been converted to function call */
4701     assert(0);
4702
4703 release :
4704     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706     pic16_freeAsmop(result,NULL,ic,TRUE); 
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genIfxJump :- will create a jump depending on the ifx           */
4711 /*-----------------------------------------------------------------*/
4712 /*
4713   note: May need to add parameter to indicate when a variable is in bit space.
4714 */
4715 static void genIfxJump (iCode *ic, char *jval)
4716 {
4717   FENTRY;
4718   
4719     /* if true label then we jump if condition
4720     supplied is true */
4721     if ( IC_TRUE(ic) ) {
4722
4723         if(strcmp(jval,"a") == 0)
4724           emitSKPZ;
4725         else if (strcmp(jval,"c") == 0)
4726           emitSKPNC;
4727         else {
4728           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4729           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4730         }
4731
4732         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4733         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4734
4735     }
4736     else {
4737         /* false label is present */
4738         if(strcmp(jval,"a") == 0)
4739           emitSKPNZ;
4740         else if (strcmp(jval,"c") == 0)
4741           emitSKPC;
4742         else {
4743           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4744           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4745         }
4746
4747         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4748         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4749
4750     }
4751
4752
4753     /* mark the icode as generated */
4754     ic->generated = 1;
4755 }
4756
4757 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4758 {
4759   FENTRY;
4760   
4761     /* if true label then we jump if condition
4762     supplied is true */
4763     if ( IC_TRUE(ic) ) {
4764       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4765       pic16_emitpcode(POC_BTFSC, jop);
4766
4767       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4768       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4769
4770     } else {
4771       /* false label is present */
4772       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4773       pic16_emitpcode(POC_BTFSS, jop);
4774           
4775       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4776       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4777     }
4778
4779
4780     /* mark the icode as generated */
4781     ic->generated = 1;
4782 }
4783
4784 #if 0
4785 // not needed ATM
4786
4787 /*-----------------------------------------------------------------*/
4788 /* genSkip                                                         */
4789 /*-----------------------------------------------------------------*/
4790 static void genSkip(iCode *ifx,int status_bit)
4791 {
4792   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4793   if(!ifx)
4794     return;
4795
4796   if ( IC_TRUE(ifx) ) {
4797     switch(status_bit) {
4798     case 'z':
4799       emitSKPNZ;
4800       break;
4801
4802     case 'c':
4803       emitSKPNC;
4804       break;
4805
4806     case 'd':
4807       emitSKPDC;
4808       break;
4809
4810     }
4811
4812     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4813     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4814
4815   } else {
4816
4817     switch(status_bit) {
4818
4819     case 'z':
4820       emitSKPZ;
4821       break;
4822
4823     case 'c':
4824       emitSKPC;
4825       break;
4826
4827     case 'd':
4828       emitSKPDC;
4829       break;
4830     }
4831     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4832     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4833
4834   }
4835
4836 }
4837 #endif
4838
4839 /*-----------------------------------------------------------------*/
4840 /* genSkipc                                                        */
4841 /*-----------------------------------------------------------------*/
4842 static void genSkipc(resolvedIfx *rifx)
4843 {
4844   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4845   
4846   if(!rifx)
4847     return;
4848
4849   if(rifx->condition)
4850     emitSKPNC;
4851   else
4852     emitSKPC;
4853
4854   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4855   rifx->generated = 1;
4856 }
4857
4858 #if !(USE_SIMPLE_GENCMP)
4859 /*-----------------------------------------------------------------*/
4860 /* genSkipz2                                                       */
4861 /*-----------------------------------------------------------------*/
4862 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4863 {
4864   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4865   
4866   if(!rifx)
4867     return;
4868
4869   if( (rifx->condition ^ invert_condition) & 1)
4870     emitSKPZ;
4871   else
4872     emitSKPNZ;
4873
4874   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4875   rifx->generated = 1;
4876 }
4877 #endif
4878
4879 #if 0
4880 /*-----------------------------------------------------------------*/
4881 /* genSkipz                                                        */
4882 /*-----------------------------------------------------------------*/
4883 static void genSkipz(iCode *ifx, int condition)
4884 {
4885   if(!ifx)
4886     return;
4887
4888   if(condition)
4889     emitSKPNZ;
4890   else
4891     emitSKPZ;
4892
4893   if ( IC_TRUE(ifx) )
4894     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4895   else
4896     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4897
4898   if ( IC_TRUE(ifx) )
4899     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4900   else
4901     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4902
4903 }
4904 #endif
4905
4906 #if !(USE_SIMPLE_GENCMP)
4907 /*-----------------------------------------------------------------*/
4908 /* genSkipCond                                                     */
4909 /*-----------------------------------------------------------------*/
4910 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4911 {
4912   if(!rifx)
4913     return;
4914
4915   if(rifx->condition)
4916     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4917   else
4918     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4919
4920
4921   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4922   rifx->generated = 1;
4923 }
4924 #endif
4925
4926 #if 0
4927 /*-----------------------------------------------------------------*/
4928 /* genChkZeroes :- greater or less than comparison                 */
4929 /*     For each byte in a literal that is zero, inclusive or the   */
4930 /*     the corresponding byte in the operand with W                */
4931 /*     returns true if any of the bytes are zero                   */
4932 /*-----------------------------------------------------------------*/
4933 static int genChkZeroes(operand *op, int lit,  int size)
4934 {
4935
4936   int i;
4937   int flag =1;
4938
4939   while(size--) {
4940     i = (lit >> (size*8)) & 0xff;
4941
4942     if(i==0) {
4943       if(flag) 
4944         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4945       else
4946         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4947       flag = 0;
4948     }
4949   }
4950
4951   return (flag==0);
4952 }
4953 #endif
4954
4955
4956 /*-----------------------------------------------------------------*/
4957 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4958 /*                  aop (if it's NOT a literal) or from lit (if    */
4959 /*                  aop is a literal)                              */
4960 /*-----------------------------------------------------------------*/
4961 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4962   if (aop->type == AOP_LIT) {
4963     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4964   } else {
4965     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4966   }
4967 }
4968
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison                       */
4971 /*-----------------------------------------------------------------*/
4972
4973 #if USE_SIMPLE_GENCMP           /* { */
4974
4975 /* genCmp performs a left < right comparison, stores
4976  * the outcome in result (if != NULL) and generates
4977  * control flow code for the ifx (if != NULL).
4978  *
4979  * This version leaves in sequences like
4980  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4981  * which should be optmized by the peephole
4982  * optimizer - RN 2005-01-01 */
4983 static void genCmp (operand *left,operand *right,
4984                     operand *result, iCode *ifx, int sign)
4985 {
4986   resolvedIfx rIfx;
4987   int size;
4988   int offs;
4989   symbol *templbl;
4990   operand *dummy;
4991   unsigned long lit;
4992   unsigned long mask;
4993   int performedLt;
4994
4995   FENTRY;
4996   
4997   assert (AOP_SIZE(left) == AOP_SIZE(right));
4998   assert (left && right);
4999
5000   size = AOP_SIZE(right) - 1;
5001   mask = (0x100UL << (size*8)) - 1;
5002   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5003   performedLt = 1;
5004   templbl = NULL;
5005   lit = 0;
5006   
5007   resolveIfx (&rIfx, ifx);
5008
5009   /* handle for special cases */
5010   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5011       return;
5012
5013   /**********************************************************************
5014    * handle bits - bit compares are promoted to int compares seemingly! *
5015    **********************************************************************/
5016 #if 0
5017   // THIS IS COMPLETELY UNTESTED!
5018   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5019     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5020     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5021     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5022
5023     emitSETC;
5024     // 1 < {0,1} is false --> clear C by skipping the next instruction
5025     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5026     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5027     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5028     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5029     emitCLRC; // only skipped for left=0 && right=1
5030
5031     goto correct_result_in_carry;
5032   } // if
5033 #endif
5034
5035   /*************************************************
5036    * make sure that left is register (or the like) *
5037    *************************************************/
5038   if (!isAOP_REGlike(left)) {
5039     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5040     assert (isAOP_LIT(left));
5041     assert (isAOP_REGlike(right));
5042     // swap left and right
5043     // left < right <==> right > left <==> (right >= left + 1)
5044     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5045
5046     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5047       // MAXVALUE < right? always false
5048       if (performedLt) emitCLRC; else emitSETC;
5049       goto correct_result_in_carry;
5050     } // if
5051
5052     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5053     // that's why we handled it above.
5054     lit++;
5055
5056     dummy = left;
5057     left = right;
5058     right = dummy;
5059
5060     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5061   } else if (isAOP_LIT(right)) {
5062     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5063   } // if
5064
5065   assert (isAOP_REGlike(left)); // left must be register or the like
5066   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5067
5068   /*************************************************
5069    * special cases go here                         *
5070    *************************************************/
5071
5072   if (isAOP_LIT(right)) {
5073     if (!sign) {
5074       // unsigned comparison to a literal
5075       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5076       if (lit == 0) {
5077         // unsigned left < 0? always false
5078         if (performedLt) emitCLRC; else emitSETC;
5079         goto correct_result_in_carry;
5080       }
5081     } else {
5082       // signed comparison to a literal
5083       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5084       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5085         // signed left < 0x80000000? always false
5086         if (performedLt) emitCLRC; else emitSETC;
5087         goto correct_result_in_carry;
5088       } else if (lit == 0) {
5089         // compare left < 0; set CARRY if SIGNBIT(left) is set
5090         if (performedLt) emitSETC; else emitCLRC;
5091         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5092         if (performedLt) emitCLRC; else emitSETC;
5093         goto correct_result_in_carry;
5094       }
5095     } // if (!sign)
5096   } // right is literal
5097
5098   /*************************************************
5099    * perform a general case comparison             *
5100    * make sure we get CARRY==1 <==> left >= right  *
5101    *************************************************/
5102   // compare most significant bytes
5103   //DEBUGpc ("comparing bytes at offset %d", size);
5104   if (!sign) {
5105     // unsigned comparison
5106     mov2w_regOrLit (AOP(right), lit, size);
5107     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5108   } else {
5109     // signed comparison
5110     // (add 2^n to both operands then perform an unsigned comparison)
5111     if (isAOP_LIT(right)) {
5112       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5113       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5114
5115       if (litbyte == 0x80) {
5116         // left >= 0x80 -- always true, but more bytes to come
5117         pic16_mov2w (AOP(left), size);
5118         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5119         emitSETC;
5120       } else {
5121         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5122         pic16_mov2w (AOP(left), size);
5123         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5125       } // if
5126     } else {
5127       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129       pic16_mov2w (AOP(left), size);
5130       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131       pic16_emitpcode (POC_MOVWF, pctemp);
5132       pic16_mov2w (AOP(right), size);
5133       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134       pic16_emitpcode (POC_SUBFW, pctemp);
5135       //pic16_popReleaseTempReg(pctemp, 1);
5136     }
5137   } // if (!sign)
5138
5139   // compare remaining bytes (treat as unsigned case from above)
5140   templbl = newiTempLabel ( NULL );
5141   offs = size;
5142   while (offs--) {
5143     //DEBUGpc ("comparing bytes at offset %d", offs);
5144     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145     mov2w_regOrLit (AOP(right), lit, offs);
5146     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5147   } // while (offs)
5148   pic16_emitpLabel (templbl->key);
5149   goto result_in_carry;
5150
5151 result_in_carry:
5152   
5153   /****************************************************
5154    * now CARRY contains the result of the comparison: *
5155    * SUBWF sets CARRY iff                             *
5156    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5157    * (F=left, W=right)                                *
5158    ****************************************************/
5159
5160   if (performedLt) {
5161     if (result && AOP_TYPE(result) != AOP_CRY) {
5162       // value will be stored
5163       emitTOGC;
5164     } else {
5165       // value wil only be used in the following genSkipc()
5166       rIfx.condition ^= 1;
5167     }
5168   } // if
5169
5170 correct_result_in_carry:
5171
5172   // assign result to variable (if neccessary)
5173   if (result && AOP_TYPE(result) != AOP_CRY) {
5174     //DEBUGpc ("assign result");
5175     size = AOP_SIZE(result);
5176     while (size--) {
5177       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5178     } // while
5179     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5180   } // if (result)
5181
5182   // perform conditional jump
5183   if (ifx) {
5184     //DEBUGpc ("generate control flow");
5185     genSkipc (&rIfx);
5186     ifx->generated = 1;
5187   } // if
5188 }
5189
5190 #elif 1         /* } */
5191                 /* { */
5192       /* original code */
5193 static void genCmp (operand *left,operand *right,
5194                     operand *result, iCode *ifx, int sign)
5195 {
5196   int size; //, offset = 0 ;
5197   unsigned long lit = 0L,i = 0;
5198   resolvedIfx rFalseIfx;
5199   //  resolvedIfx rTrueIfx;
5200   symbol *truelbl;
5201   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5202 /*
5203   if(ifx) {
5204     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5206   }
5207 */
5208
5209   FENTRY;
5210   
5211   resolveIfx(&rFalseIfx,ifx);
5212   truelbl  = newiTempLabel(NULL);
5213   size = max(AOP_SIZE(left),AOP_SIZE(right));
5214
5215   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5216
5217 #define _swapp
5218
5219   /* if literal is on the right then swap with left */
5220   if ((AOP_TYPE(right) == AOP_LIT)) {
5221     operand *tmp = right ;
5222     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5224 #ifdef _swapp
5225
5226     lit = (lit - 1) & mask;
5227     right = left;
5228     left = tmp;
5229     rFalseIfx.condition ^= 1;
5230 #endif
5231
5232   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5234   }
5235
5236
5237   //if(IC_TRUE(ifx) == NULL)
5238   /* if left & right are bit variables */
5239   if (AOP_TYPE(left) == AOP_CRY &&
5240       AOP_TYPE(right) == AOP_CRY ) {
5241     assert (0 && "bit variables used in genCmp");
5242     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5244   } else {
5245     /* subtract right from left if at the
5246        end the carry flag is set then we know that
5247        left is greater than right */
5248
5249     symbol *lbl  = newiTempLabel(NULL);
5250
5251 #if 0
5252         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5254 #endif
5255
5256 #ifndef _swapp
5257     if(AOP_TYPE(right) == AOP_LIT) {
5258
5259       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5260
5261       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5262
5263       /* special cases */
5264
5265       if(lit == 0) {
5266
5267         if(sign != 0) 
5268           genSkipCond(&rFalseIfx,left,size-1,7);
5269         else 
5270           /* no need to compare to 0...*/
5271           /* NOTE: this is a de-generate compare that most certainly 
5272            *       creates some dead code. */
5273           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5274
5275         if(ifx) ifx->generated = 1;
5276         return;
5277
5278       }
5279       size--;
5280
5281       if(size == 0) {
5282         //i = (lit >> (size*8)) & 0xff;
5283         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5284         
5285         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5286
5287         i = ((0-lit) & 0xff);
5288         if(sign) {
5289           if( i == 0x81) { 
5290             /* lit is 0x7f, all signed chars are less than
5291              * this except for 0x7f itself */
5292             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293             genSkipz2(&rFalseIfx,0);
5294           } else {
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297             genSkipc(&rFalseIfx);
5298           }
5299
5300         } else {
5301           if(lit == 1) {
5302             genSkipz2(&rFalseIfx,1);
5303           } else {
5304             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305             genSkipc(&rFalseIfx);
5306           }
5307         }
5308
5309         if(ifx) ifx->generated = 1;
5310         return;
5311       }
5312
5313       /* chars are out of the way. now do ints and longs */
5314
5315
5316       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5317         
5318       /* special cases */
5319
5320       if(sign) {
5321
5322         if(lit == 0) {
5323           genSkipCond(&rFalseIfx,left,size,7);
5324           if(ifx) ifx->generated = 1;
5325           return;
5326         }
5327
5328         if(lit <0x100) {
5329           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330
5331           //rFalseIfx.condition ^= 1;
5332           //genSkipCond(&rFalseIfx,left,size,7);
5333           //rFalseIfx.condition ^= 1;
5334
5335           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336           if(rFalseIfx.condition)
5337             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5338           else
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5340
5341           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5344
5345           while(size > 1)
5346             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5347
5348           if(rFalseIfx.condition) {
5349             emitSKPZ;
5350             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5351
5352           } else {
5353             emitSKPNZ;
5354           }
5355
5356           genSkipc(&rFalseIfx);
5357           pic16_emitpLabel(truelbl->key);
5358           if(ifx) ifx->generated = 1;
5359           return;
5360
5361         }
5362
5363         if(size == 1) {
5364
5365           if( (lit & 0xff) == 0) {
5366             /* lower byte is zero */
5367             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368             i = ((lit >> 8) & 0xff) ^0x80;
5369             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372             genSkipc(&rFalseIfx);
5373
5374
5375             if(ifx) ifx->generated = 1;
5376             return;
5377
5378           }
5379         } else {
5380           /* Special cases for signed longs */
5381           if( (lit & 0xffffff) == 0) {
5382             /* lower byte is zero */
5383             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384             i = ((lit >> 8*3) & 0xff) ^0x80;
5385             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388             genSkipc(&rFalseIfx);
5389
5390
5391             if(ifx) ifx->generated = 1;
5392             return;
5393
5394           }
5395
5396         }
5397
5398
5399         if(lit & (0x80 << (size*8))) {
5400           /* lit is negative */
5401           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5402
5403           //genSkipCond(&rFalseIfx,left,size,7);
5404
5405           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5406
5407           if(rFalseIfx.condition)
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5409           else
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5411
5412
5413         } else {
5414           /* lit is positive */
5415           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417           if(rFalseIfx.condition)
5418             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5419           else
5420             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5421
5422         }
5423
5424         /*
5425           This works, but is only good for ints.
5426           It also requires a "known zero" register.
5427           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5430           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432           genSkipc(&rFalseIfx);
5433
5434           pic16_emitpLabel(truelbl->key);
5435           if(ifx) ifx->generated = 1;
5436           return;
5437         **/
5438           
5439         /* There are no more special cases, so perform a general compare */
5440   
5441         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443
5444         while(size--) {
5445
5446           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5447           emitSKPNZ;
5448           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5449         }
5450         //rFalseIfx.condition ^= 1;
5451         genSkipc(&rFalseIfx);
5452
5453         pic16_emitpLabel(truelbl->key);
5454
5455         if(ifx) ifx->generated = 1;
5456         return;
5457
5458
5459       }
5460
5461
5462       /* sign is out of the way. So now do an unsigned compare */
5463       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5464
5465
5466       /* General case - compare to an unsigned literal on the right.*/
5467
5468       i = (lit >> (size*8)) & 0xff;
5469       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5471       while(size--) {
5472         i = (lit >> (size*8)) & 0xff;
5473
5474         if(i) {
5475           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5476           emitSKPNZ;
5477           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5478         } else {
5479           /* this byte of the lit is zero, 
5480            *if it's not the last then OR in the variable */
5481           if(size)
5482             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5483         }
5484       }
5485
5486
5487       pic16_emitpLabel(lbl->key);
5488 //      pic16_emitpLabel(truelbl->key);
5489       //if(emitFinalCheck)
5490       genSkipc(&rFalseIfx);
5491       if(sign)
5492         pic16_emitpLabel(truelbl->key);
5493
5494       if(ifx) ifx->generated = 1;
5495       return;
5496
5497
5498     }
5499 #endif  // _swapp
5500
5501     if(AOP_TYPE(left) == AOP_LIT) {
5502       //symbol *lbl = newiTempLabel(NULL);
5503
5504       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5505
5506
5507       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5508
5509       /* Special cases */
5510       if((lit == 0) && (sign == 0)){
5511
5512         size--;
5513         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5514         while(size) 
5515           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5516
5517         genSkipz2(&rFalseIfx,0);
5518         if(ifx) ifx->generated = 1;
5519         return;
5520       }
5521
5522       if(size==1) {
5523         /* Special cases */
5524         lit &= 0xff;
5525         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526           /* degenerate compare can never be true */
5527           if(rFalseIfx.condition == 0)
5528             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5529
5530           if(ifx) ifx->generated = 1;
5531           return;
5532         }
5533
5534         if(sign) {
5535           /* signed comparisons to a literal byte */
5536
5537           int lp1 = (lit+1) & 0xff;
5538
5539           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5540           switch (lp1) {
5541           case 0:
5542             rFalseIfx.condition ^= 1;
5543             genSkipCond(&rFalseIfx,right,0,7);
5544             break;
5545           case 0x7f:
5546             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548             genSkipz2(&rFalseIfx,1);
5549             break;
5550           default:
5551             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554             rFalseIfx.condition ^= 1;
5555             genSkipc(&rFalseIfx);
5556             break;
5557           }
5558         } else {
5559           /* unsigned comparisons to a literal byte */
5560
5561           switch(lit & 0xff ) {
5562           case 0:
5563             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564             genSkipz2(&rFalseIfx,0);
5565             break;
5566           case 0x7f:
5567             rFalseIfx.condition ^= 1;
5568             genSkipCond(&rFalseIfx,right,0,7);
5569             break;
5570
5571           default:
5572             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5575             rFalseIfx.condition ^= 1;
5576             if (AOP_TYPE(result) == AOP_CRY)
5577               genSkipc(&rFalseIfx);
5578             else {
5579               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5581             }         
5582             break;
5583           }
5584         }
5585
5586         if(ifx) ifx->generated = 1;
5587         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5588                 goto check_carry;
5589         return;
5590
5591       } else {
5592
5593         /* Size is greater than 1 */
5594
5595         if(sign) {
5596           int lp1 = lit+1;
5597
5598           size--;
5599
5600           if(lp1 == 0) {
5601             /* this means lit = 0xffffffff, or -1 */
5602
5603
5604             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605             rFalseIfx.condition ^= 1;
5606             genSkipCond(&rFalseIfx,right,size,7);
5607             if(ifx) ifx->generated = 1;
5608
5609             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5610               goto check_carry;
5611
5612             return;
5613           }
5614
5615           if(lit == 0) {
5616             int s = size;
5617
5618             if(rFalseIfx.condition) {
5619               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5621             }
5622
5623             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5624             while(size--)
5625               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5626
5627
5628             emitSKPZ;
5629             if(rFalseIfx.condition) {
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5631               pic16_emitpLabel(truelbl->key);
5632             }else {
5633               rFalseIfx.condition ^= 1;
5634               genSkipCond(&rFalseIfx,right,s,7);
5635             }
5636
5637             if(ifx) ifx->generated = 1;
5638
5639             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5640               goto check_carry;
5641
5642             return;
5643           }
5644
5645           if((size == 1) &&  (0 == (lp1&0xff))) {
5646             /* lower byte of signed word is zero */
5647             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5648             i = ((lp1 >> 8) & 0xff) ^0x80;
5649             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5652
5653             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5654               emitTOGC;
5655               if(ifx) ifx->generated = 1;
5656               goto check_carry;
5657             } else {
5658               rFalseIfx.condition ^= 1;
5659               genSkipc(&rFalseIfx);
5660               if(ifx) ifx->generated = 1;
5661             }
5662
5663             return;
5664           }
5665
5666           if(lit & (0x80 << (size*8))) {
5667             /* Lit is less than zero */
5668             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5669             //rFalseIfx.condition ^= 1;
5670             //genSkipCond(&rFalseIfx,left,size,7);
5671             //rFalseIfx.condition ^= 1;
5672             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5674
5675             if(rFalseIfx.condition)
5676               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5677             else
5678               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5679
5680
5681           } else {
5682             /* Lit is greater than or equal to zero */
5683             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5684             //rFalseIfx.condition ^= 1;
5685             //genSkipCond(&rFalseIfx,right,size,7);
5686             //rFalseIfx.condition ^= 1;
5687
5688             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5690
5691             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692             if(rFalseIfx.condition)
5693               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5694             else
5695               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5696
5697           }
5698
5699           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701
5702           while(size--) {
5703
5704             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5705             emitSKPNZ;
5706             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5707           }
5708           rFalseIfx.condition ^= 1;
5709           //rFalseIfx.condition = 1;
5710           genSkipc(&rFalseIfx);
5711
5712           pic16_emitpLabel(truelbl->key);
5713
5714           if(ifx) ifx->generated = 1;
5715
5716
5717           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5718             goto check_carry;
5719
5720           return;
5721           // end of if (sign)
5722         } else {
5723
5724           /* compare word or long to an unsigned literal on the right.*/
5725
5726
5727           size--;
5728           if(lit < 0xff) {
5729             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5730             switch (lit) {
5731             case 0:
5732               break; /* handled above */
5733 /*
5734             case 0xff:
5735               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5736               while(size--)
5737                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738               genSkipz2(&rFalseIfx,0);
5739               break;
5740 */
5741             default:
5742               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5743               while(--size)
5744                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5745
5746               emitSKPZ;
5747               if(rFalseIfx.condition)
5748                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5749               else
5750                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5751
5752
5753               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5755
5756               rFalseIfx.condition ^= 1;
5757               genSkipc(&rFalseIfx);
5758             }
5759
5760             pic16_emitpLabel(truelbl->key);
5761
5762             if(ifx) ifx->generated = 1;
5763
5764             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5765               goto check_carry;
5766
5767             return;
5768           }
5769
5770
5771           lit++;
5772           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773           i = (lit >> (size*8)) & 0xff;
5774
5775           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5777
5778           while(size--) {
5779             i = (lit >> (size*8)) & 0xff;
5780
5781             if(i) {
5782               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5783               emitSKPNZ;
5784               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5785             } else {
5786               /* this byte of the lit is zero, 
5787                * if it's not the last then OR in the variable */
5788               if(size)
5789                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5790             }
5791           }
5792
5793
5794           pic16_emitpLabel(lbl->key);
5795
5796           rFalseIfx.condition ^= 1;
5797
5798           genSkipc(&rFalseIfx);
5799         }
5800
5801         if(sign)
5802           pic16_emitpLabel(truelbl->key);
5803         if(ifx) ifx->generated = 1;
5804
5805             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5806               goto check_carry;
5807
5808         return;
5809       }
5810     }
5811     /* Compare two variables */
5812
5813     DEBUGpic16_emitcode(";sign","%d",sign);
5814
5815     size--;
5816     if(sign) {
5817       /* Sigh. thus sucks... */
5818       if(size) {
5819         pCodeOp *pctemp;
5820         
5821         pctemp = pic16_popGetTempReg(1);
5822         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_popReleaseTempReg(pctemp, 1);
5829       } else {
5830         /* Signed char comparison */
5831         /* Special thanks to Nikolai Golovchenko for this snippet */
5832         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5835         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5838
5839         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5840         genSkipc(&rFalseIfx);
5841           
5842         if(ifx) ifx->generated = 1;
5843
5844             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5845               goto check_carry;
5846
5847         return;
5848       }
5849
5850     } else {
5851
5852       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854     }
5855
5856
5857     /* The rest of the bytes of a multi-byte compare */
5858     while (size) {
5859
5860       emitSKPZ;
5861       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5862       size--;
5863
5864       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5866
5867
5868     }
5869
5870     pic16_emitpLabel(lbl->key);
5871
5872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5873     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5874         (AOP_TYPE(result) == AOP_REG)) {
5875       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5877     } else {
5878       genSkipc(&rFalseIfx);
5879     }         
5880     //genSkipc(&rFalseIfx);
5881     if(ifx) ifx->generated = 1;
5882
5883
5884             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5885               goto check_carry;
5886
5887     return;
5888
5889   }
5890
5891 check_carry:
5892   if ((AOP_TYPE(result) != AOP_CRY) 
5893         && AOP_SIZE(result)) {
5894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5895
5896     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5897
5898     pic16_outBitC(result);
5899   } else {
5900     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5901     /* if the result is used in the next
5902        ifx conditional branch then generate
5903        code a little differently */
5904     if (ifx )
5905       genIfxJump (ifx,"c");
5906     else
5907       pic16_outBitC(result);
5908     /* leave the result in acc */
5909   }
5910
5911 }
5912
5913 #elif 0 /* VR version of genCmp() */    /* } else { */
5914
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917         operand *result, int offset, int invert_op)
5918 {
5919   /* add code here */
5920   
5921   /* check condition, > or < ?? */
5922   if(rIfx->condition != 0)invert_op ^= 1;
5923   
5924   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5925
5926   if(!ifx)invert_op ^= 1;
5927
5928   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5930   
5931   /* do selection */
5932   if(!invert_op)return POC_CPFSGT;
5933   else return POC_CPFSLT;
5934 }
5935
5936 static int compareAopfirstpass=1;
5937
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939             operand *oper, int offset, operand *result,
5940             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5941             symbol *tlbl)
5942 {
5943   int op;
5944   symbol *truelbl;
5945
5946   /* invert if there is a result to be loaded, in order to fit,
5947    * SETC/CLRC sequence */
5948   if(AOP_SIZE(result))invert_op ^= 1;
5949
5950 //  if(sign && !offset)invert_op ^= 1;
5951   
5952 //  if(sign)invert_op ^= 1;
5953   
5954   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5955
5956   if(AOP_SIZE(result) && compareAopfirstpass) {
5957     if(!ifx) {
5958       if(pcop2)
5959         pic16_emitpcode(POC_SETF, pcop2);
5960       else
5961         emitSETC;
5962     } else {
5963       if(pcop2)
5964         pic16_emitpcode(POC_CLRF, pcop2);
5965       else
5966         emitCLRC;
5967     }
5968   }
5969
5970   compareAopfirstpass = 0;
5971
5972       /* there is a bug when comparing operands with size > 1,
5973        * because higher bytes can be equal and test should be performed
5974        * to the next lower byte, current algorithm, considers operands
5975        * inequal in these cases! -- VR 20041107 */
5976
5977     
5978   if(pcop)
5979     pic16_emitpcode(op, pcop);
5980   else
5981     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5982
5983
5984   if((!sign || !offset) && AOP_SIZE(result)) {
5985     if(!ifx) {
5986       if(pcop2)
5987         pic16_emitpcode(POC_CLRF, pcop2);
5988         else
5989         emitCLRC;
5990     } else {
5991       if(pcop2)
5992         pic16_emitpcode(POC_SETF, pcop2);
5993       else
5994         emitSETC;
5995     }
5996     
5997     /* don't emit final branch (offset == 0) */
5998     if(offset) {
5999
6000       if(pcop2)
6001         pic16_emitpcode(POC_RRCF, pcop2);
6002
6003       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6004     }
6005   } else {
6006     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6009
6010       truelbl = newiTempLabel( NULL );
6011       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6014       else
6015         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016       pic16_emitpLabel(truelbl->key);
6017     } else {
6018       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6019     }
6020   }
6021 }
6022
6023 static void genCmp (operand *left, operand *right,
6024                     operand *result, iCode *ifx, int sign)
6025 {
6026   int size, cmpop=1;
6027   long lit = 0L;
6028   resolvedIfx rFalseIfx;
6029   symbol *falselbl, *tlbl;
6030
6031     FENTRY;
6032     
6033     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6034
6035     resolveIfx(&rFalseIfx, ifx);
6036     size = max(AOP_SIZE(left), AOP_SIZE(right));
6037     
6038     /* if left & right are bit variables */
6039     if(AOP_TYPE(left) == AOP_CRY
6040       && AOP_TYPE(right) == AOP_CRY ) {
6041
6042         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6044         
6045         werror(W_POSSBUG2, __FILE__, __LINE__);
6046         exit(-1);
6047     }
6048     
6049     /* if literal is on the right then swap with left */
6050     if((AOP_TYPE(right) == AOP_LIT)) {
6051       operand *tmp = right ;
6052 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6053
6054         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6055
6056 //      lit = (lit - 1) & mask;
6057         right = left;
6058         left = tmp;
6059         rFalseIfx.condition ^= 1;               /* reverse compare */
6060     } else
6061     if ((AOP_TYPE(left) == AOP_LIT)) {
6062       /* float compares are handled by support functions */
6063       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6064     }
6065
6066     /* actual comparing algorithm */
6067 //    size = AOP_SIZE( right );
6068
6069     falselbl = newiTempLabel( NULL );
6070     if(AOP_TYPE(left) == AOP_LIT) {
6071       /* compare to literal */
6072       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6073       
6074       if(sign) {
6075         pCodeOp *pct, *pct2;
6076         symbol *tlbl1;
6077
6078         /* signed compare */
6079         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6080
6081         pct = pic16_popCopyReg(&pic16_pc_prodl);
6082         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6083         tlbl = newiTempLabel( NULL );
6084         
6085         /* first compare signs:
6086          *  a. if both are positive, compare just like unsigned
6087          *  b. if both are negative, invert cmpop, compare just like unsigned
6088          *  c. if different signs, determine the result directly */
6089
6090         size--;
6091
6092 #if 1
6093         /* { */
6094         tlbl1 = newiTempLabel( NULL );
6095 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6096
6097         if(lit > 0) {
6098
6099           /* literal is zero or positive:
6100            *  a. if carry is zero, too, continue compare,
6101            *  b. if carry is set, then continue depending on cmpop ^ condition:
6102            *    1. '<' return false (literal < variable),
6103            *    2. '>' return true (literal > variable) */
6104 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6105           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6106           
6107           
6108           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6109           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6110         } else 
6111         if(lit < 0) {
6112           
6113           /* literal is negative:
6114            *  a. if carry is set, too, continue compare,
6115            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6116            *    1. '<' return true (literal < variable),
6117            *    2. '>' return false (literal > variable) */
6118 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6119           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6120           
6121           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6123         }
6124 #if 1
6125         else {
6126           /* lit == 0 */
6127           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6128           
6129           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6130           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6131         }
6132 #endif
6133         
6134         
6135         pic16_emitpLabel( tlbl1->key );
6136 #endif  /* } */
6137
6138         compareAopfirstpass=1;
6139 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6141 //        pic16_emitpcode(POC_MOVWF, pct);
6142
6143 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6144         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6145 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147
6148         /* generic case */        
6149           while( size-- ) {
6150 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6151 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6152 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6153 //            pic16_emitpcode(POC_MOVWF, pct);
6154
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6156             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6157             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6158 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6160           }
6161         
6162         if(ifx)ifx->generated = 1;
6163
6164         if(AOP_SIZE(result)) {
6165           pic16_emitpLabel(tlbl->key);
6166           pic16_emitpLabel(falselbl->key);
6167           pic16_outBitOp( result, pct2 );
6168         } else {
6169           pic16_emitpLabel(tlbl->key);
6170         }
6171       } else {
6172
6173         /* unsigned compare */      
6174         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175     
6176         compareAopfirstpass=1;
6177         while(size--) {
6178           
6179           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181
6182         }
6183         if(ifx)ifx->generated = 1;
6184
6185         if(AOP_SIZE(result)) {
6186           pic16_emitpLabel(falselbl->key);
6187           pic16_outBitC( result );
6188         }
6189
6190       }
6191     } else {
6192       /* compare registers */
6193       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6194
6195
6196       if(sign) {
6197         pCodeOp *pct, *pct2;
6198         
6199         /* signed compare */
6200         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6201
6202         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6203         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6204         tlbl = newiTempLabel( NULL );
6205         
6206         compareAopfirstpass=1;
6207
6208         size--;
6209         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6210 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6211         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212         pic16_emitpcode(POC_MOVWF, pct);
6213
6214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6215 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217
6218         /* WREG already holds left + 0x80 */
6219         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6220         
6221         while( size-- ) {
6222           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6223 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6224           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225           pic16_emitpcode(POC_MOVWF, pct);
6226                 
6227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6228 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230
6231           /* WREG already holds left + 0x80 */
6232           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6233 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6234         }
6235         
6236         if(ifx)ifx->generated = 1;
6237
6238         if(AOP_SIZE(result)) {
6239           pic16_emitpLabel(tlbl->key);
6240           pic16_emitpLabel(falselbl->key);
6241           pic16_outBitOp( result, pct2 );
6242         } else {
6243           pic16_emitpLabel(tlbl->key);
6244         }
6245
6246       } else {
6247         /* unsigned compare */      
6248         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6249
6250         compareAopfirstpass=1;
6251         while(size--) {
6252           
6253           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6254           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6255
6256         }
6257
6258         if(ifx)ifx->generated = 1;
6259         if(AOP_SIZE(result)) {
6260
6261           pic16_emitpLabel(falselbl->key);
6262           pic16_outBitC( result );
6263         }
6264
6265       }
6266     }
6267 }
6268
6269 #endif  /* } */
6270
6271
6272
6273 /*-----------------------------------------------------------------*/
6274 /* genCmpGt :- greater than comparison                             */
6275 /*-----------------------------------------------------------------*/
6276 static void genCmpGt (iCode *ic, iCode *ifx)
6277 {
6278   operand *left, *right, *result;
6279   sym_link *letype , *retype;
6280   int sign ;
6281
6282     FENTRY;
6283     
6284     left = IC_LEFT(ic);
6285     right= IC_RIGHT(ic);
6286     result = IC_RESULT(ic);
6287
6288     letype = getSpec(operandType(left));
6289     retype =getSpec(operandType(right));
6290     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6291     /* assign the amsops */
6292     pic16_aopOp (left,ic,FALSE);
6293     pic16_aopOp (right,ic,FALSE);
6294     pic16_aopOp (result,ic,TRUE);
6295
6296     genCmp(right, left, result, ifx, sign);
6297
6298     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300     pic16_freeAsmop(result,NULL,ic,TRUE); 
6301 }
6302
6303 /*-----------------------------------------------------------------*/
6304 /* genCmpLt - less than comparisons                                */
6305 /*-----------------------------------------------------------------*/
6306 static void genCmpLt (iCode *ic, iCode *ifx)
6307 {
6308   operand *left, *right, *result;
6309   sym_link *letype , *retype;
6310   int sign ;
6311
6312     FENTRY;
6313
6314     left = IC_LEFT(ic);
6315     right= IC_RIGHT(ic);
6316     result = IC_RESULT(ic);
6317
6318     letype = getSpec(operandType(left));
6319     retype =getSpec(operandType(right));
6320     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6321
6322     /* assign the amsops */
6323     pic16_aopOp (left,ic,FALSE);
6324     pic16_aopOp (right,ic,FALSE);
6325     pic16_aopOp (result,ic,TRUE);
6326
6327     genCmp(left, right, result, ifx, sign);
6328
6329     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331     pic16_freeAsmop(result,NULL,ic,TRUE); 
6332 }
6333
6334 #if 0
6335 // not needed ATM
6336 // FIXME reenable literal optimisation when the pic16 port is stable
6337
6338 /*-----------------------------------------------------------------*/
6339 /* genc16bit2lit - compare a 16 bit value to a literal             */
6340 /*-----------------------------------------------------------------*/
6341 static void genc16bit2lit(operand *op, int lit, int offset)
6342 {
6343   int i;
6344
6345   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6346   if( (lit&0xff) == 0) 
6347     i=1;
6348   else
6349     i=0;
6350
6351   switch( BYTEofLONG(lit,i)) { 
6352   case 0:
6353     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6354     break;
6355   case 1:
6356     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6357     break;
6358   case 0xff:
6359     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6360     break;
6361   default:
6362     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6363     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6364   }
6365
6366   i ^= 1;
6367
6368   switch( BYTEofLONG(lit,i)) { 
6369   case 0:
6370     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6371     break;
6372   case 1:
6373     emitSKPNZ;
6374     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   case 0xff:
6377     emitSKPNZ;
6378     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6379     break;
6380   default:
6381     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6382     emitSKPNZ;
6383     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6384
6385   }
6386
6387 }
6388 #endif
6389
6390 #if 0
6391 // not needed ATM
6392 /*-----------------------------------------------------------------*/
6393 /* gencjneshort - compare and jump if not equal                    */
6394 /*-----------------------------------------------------------------*/
6395 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6396 {
6397   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6398   int offset = 0;
6399   int res_offset = 0;  /* the result may be a different size then left or right */
6400   int res_size = AOP_SIZE(result);
6401   resolvedIfx rIfx;
6402   symbol *lbl, *lbl_done;
6403
6404   unsigned long lit = 0L;
6405   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6406
6407   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6408   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6409   if(result)
6410     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6411   resolveIfx(&rIfx,ifx);
6412   lbl =  newiTempLabel(NULL);
6413   lbl_done =  newiTempLabel(NULL);
6414
6415
6416   /* if the left side is a literal or 
6417      if the right is in a pointer register and left 
6418      is not */
6419   if ((AOP_TYPE(left) == AOP_LIT) || 
6420       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6421     operand *t = right;
6422     right = left;
6423     left = t;
6424   }
6425   if(AOP_TYPE(right) == AOP_LIT)
6426     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6427
6428   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6429     preserve_result = 1;
6430
6431   if(result && !preserve_result)
6432     {
6433       int i;
6434       for(i = 0; i < AOP_SIZE(result); i++)
6435         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6436     }
6437
6438
6439   /* if the right side is a literal then anything goes */
6440   if (AOP_TYPE(right) == AOP_LIT &&
6441       AOP_TYPE(left) != AOP_DIR ) {
6442     switch(size) {
6443     case 2:
6444       genc16bit2lit(left, lit, 0);
6445       emitSKPZ;
6446       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6447       break;
6448     default:
6449       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6450       while (size--) {
6451         if(lit & 0xff) {
6452           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6454         } else {
6455           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6456         }
6457
6458         emitSKPZ;
6459         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6460         offset++;
6461         if(res_offset < res_size-1)
6462           res_offset++;
6463         lit >>= 8;
6464       }
6465       break;
6466     }
6467   }
6468
6469   /* if the right side is in a register or in direct space or
6470      if the left is a pointer register & right is not */    
6471   else if (AOP_TYPE(right) == AOP_REG ||
6472            AOP_TYPE(right) == AOP_DIR || 
6473            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6474            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6475     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6476     int lbl_key = lbl->key;
6477
6478     if(result) {
6479       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6480       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6481     }else {
6482       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6483       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6484               __FUNCTION__,__LINE__);
6485       return;
6486     }
6487    
6488 /*     switch(size) { */
6489 /*     case 2: */
6490 /*       genc16bit2lit(left, lit, 0); */
6491 /*       emitSKPNZ; */
6492 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6493 /*       break; */
6494 /*     default: */
6495     while (size--) {
6496       int emit_skip=1;
6497       if((AOP_TYPE(left) == AOP_DIR) && 
6498          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6499
6500         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6501         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6502
6503       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6504             
6505         switch (lit & 0xff) {
6506         case 0:
6507           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6508           break;
6509         case 1:
6510           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6511           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6513           emit_skip=0;
6514           break;
6515         case 0xff:
6516           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6518           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6520           emit_skip=0;
6521           break;
6522         default:
6523           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6524           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6525         }
6526         lit >>= 8;
6527
6528       } else {
6529         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6530       }
6531       if(emit_skip) {
6532         if(AOP_TYPE(result) == AOP_CRY) {
6533           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6534           if(rIfx.condition)
6535             emitSKPNZ;
6536           else
6537             emitSKPZ;
6538           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6539         } else {
6540           /* fix me. probably need to check result size too */
6541           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6542           if(rIfx.condition)
6543             emitSKPZ;
6544           else
6545             emitSKPNZ;
6546           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6547           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6548         }
6549         if(ifx)
6550           ifx->generated=1;
6551       }
6552       emit_skip++;
6553       offset++;
6554       if(res_offset < res_size-1)
6555         res_offset++;
6556     }
6557 /*       break; */
6558 /*     } */
6559   } else if(AOP_TYPE(right) == AOP_REG &&
6560             AOP_TYPE(left) != AOP_DIR){
6561
6562     while(size--) {
6563       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6564       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6565       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6566       if(rIfx.condition)
6567         emitSKPNZ;
6568       else
6569         emitSKPZ;
6570       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6571       offset++;
6572       if(res_offset < res_size-1)
6573         res_offset++;
6574     }
6575       
6576   }else{
6577     /* right is a pointer reg need both a & b */
6578     while(size--) {
6579       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6580       if(strcmp(l,"b"))
6581         pic16_emitcode("mov","b,%s",l);
6582       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6583       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6584       offset++;
6585     }
6586   }
6587
6588   if(result && preserve_result)
6589     {
6590       int i;
6591       for(i = 0; i < AOP_SIZE(result); i++)
6592         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6593     }
6594
6595   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6596
6597   if(result && preserve_result)
6598     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6599
6600   if(!rIfx.condition)
6601     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6602
6603   pic16_emitpLabel(lbl->key);
6604
6605   if(result && preserve_result)
6606     {
6607       int i;
6608       for(i = 0; i < AOP_SIZE(result); i++)
6609         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6610
6611       pic16_emitpLabel(lbl_done->key);
6612    }
6613
6614   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6615
6616   if(ifx)
6617     ifx->generated = 1;
6618 }
6619 #endif
6620
6621 #if 0
6622 /*-----------------------------------------------------------------*/
6623 /* gencjne - compare and jump if not equal                         */
6624 /*-----------------------------------------------------------------*/
6625 static void gencjne(operand *left, operand *right, iCode *ifx)
6626 {
6627     symbol *tlbl  = newiTempLabel(NULL);
6628
6629     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6630     gencjneshort(left, right, lbl);
6631
6632     pic16_emitcode("mov","a,%s",one);
6633     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6634     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6635     pic16_emitcode("clr","a");
6636     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6637
6638     pic16_emitpLabel(lbl->key);
6639     pic16_emitpLabel(tlbl->key);
6640
6641 }
6642 #endif
6643
6644
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitOp - check if operand has to be treated as literal        */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitOp(operand *op)
6649 {
6650   return ((AOP_TYPE(op) == AOP_LIT)
6651       || ( (AOP_TYPE(op) == AOP_PCODE)
6652           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6653               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6654 }
6655
6656 /*-----------------------------------------------------------------*/
6657 /* is_LitAOp - check if operand has to be treated as literal        */
6658 /*-----------------------------------------------------------------*/
6659 static bool is_LitAOp(asmop *aop)
6660 {
6661   return ((aop->type == AOP_LIT)
6662       || ( (aop->type == AOP_PCODE)
6663           && ( (aop->aopu.pcop->type == PO_LITERAL)
6664               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6665 }
6666
6667
6668
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpEq - generates code for equal to                          */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpEq (iCode *ic, iCode *ifx)
6673 {
6674   operand *left, *right, *result;
6675   symbol *falselbl = newiTempLabel(NULL);
6676   symbol *donelbl = newiTempLabel(NULL);
6677
6678   int preserve_result = 0;
6679   int generate_result = 0;
6680   int i=0;
6681   unsigned long lit = -1;
6682
6683   FENTRY;
6684   
6685   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6686   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6687   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6688  
6689   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6690
6691   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6692     {
6693       werror(W_POSSBUG2, __FILE__, __LINE__);
6694       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6695       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6696       goto release;
6697     }
6698
6699   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6700     {
6701       operand *tmp = right ;
6702       right = left;
6703       left = tmp;
6704     }
6705
6706   if (AOP_TYPE(right) == AOP_LIT) {
6707     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6708   }
6709
6710   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6711     preserve_result = 1;
6712
6713   if(result && AOP_SIZE(result))
6714     generate_result = 1;
6715
6716   if(generate_result && !preserve_result)
6717     {
6718       for(i = 0; i < AOP_SIZE(result); i++)
6719         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6720     }
6721
6722   for(i=0; i < AOP_SIZE(left); i++)
6723     {
6724       if(AOP_TYPE(left) != AOP_ACC)
6725         {
6726           if(is_LitOp(left))
6727             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6728           else
6729             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6730         }
6731       if(is_LitOp(right)) {
6732         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6733           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6734         }
6735       } else
6736         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6737
6738       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6739     }
6740
6741   // result == true
6742
6743   if(generate_result && preserve_result)
6744     {
6745       for(i = 0; i < AOP_SIZE(result); i++)
6746         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6747     }
6748
6749   if(generate_result)
6750     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6751
6752   if(generate_result && preserve_result)
6753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6754
6755   if(ifx && IC_TRUE(ifx))
6756     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6757
6758   if(ifx && IC_FALSE(ifx))
6759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760
6761   pic16_emitpLabel(falselbl->key);
6762
6763   // result == false
6764
6765   if(ifx && IC_FALSE(ifx))
6766     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6767
6768   if(generate_result && preserve_result)
6769     {
6770       for(i = 0; i < AOP_SIZE(result); i++)
6771         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6772     }
6773
6774   pic16_emitpLabel(donelbl->key);
6775
6776   if(ifx)
6777     ifx->generated = 1;
6778
6779 release:
6780   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6782   pic16_freeAsmop(result,NULL,ic,TRUE);
6783
6784 }
6785
6786
6787 #if 0
6788 // old version kept for reference
6789
6790 /*-----------------------------------------------------------------*/
6791 /* genCmpEq - generates code for equal to                          */
6792 /*-----------------------------------------------------------------*/
6793 static void genCmpEq (iCode *ic, iCode *ifx)
6794 {
6795     operand *left, *right, *result;
6796     unsigned long lit = 0L;
6797     int size,offset=0;
6798     symbol *falselbl  = newiTempLabel(NULL);
6799
6800
6801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6802
6803     if(ifx)
6804       DEBUGpic16_emitcode ("; ifx is non-null","");
6805     else
6806       DEBUGpic16_emitcode ("; ifx is null","");
6807
6808     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6809     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6810     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6811
6812     size = max(AOP_SIZE(left),AOP_SIZE(right));
6813
6814     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6815
6816     /* if literal, literal on the right or 
6817     if the right is in a pointer register and left 
6818     is not */
6819     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6820         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821       operand *tmp = right ;
6822       right = left;
6823       left = tmp;
6824     }
6825
6826
6827     if(ifx && !AOP_SIZE(result)){
6828         symbol *tlbl;
6829         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6830         /* if they are both bit variables */
6831         if (AOP_TYPE(left) == AOP_CRY &&
6832             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6833                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6834             if(AOP_TYPE(right) == AOP_LIT){
6835                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6836                 if(lit == 0L){
6837                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838                     pic16_emitcode("cpl","c");
6839                 } else if(lit == 1L) {
6840                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6841                 } else {
6842                     pic16_emitcode("clr","c");
6843                 }
6844                 /* AOP_TYPE(right) == AOP_CRY */
6845             } else {
6846                 symbol *lbl = newiTempLabel(NULL);
6847                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6849                 pic16_emitcode("cpl","c");
6850                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6851             }
6852             /* if true label then we jump if condition
6853             supplied is true */
6854             tlbl = newiTempLabel(NULL);
6855             if ( IC_TRUE(ifx) ) {
6856                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6857                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6858             } else {
6859                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6860                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6861             }
6862             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6863
6864                 {
6865                 /* left and right are both bit variables, result is carry */
6866                         resolvedIfx rIfx;
6867               
6868                         resolveIfx(&rIfx,ifx);
6869
6870                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6871                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6872                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6873                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6874                         genSkipz2(&rIfx,0);
6875                 }
6876         } else {
6877
6878                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6879
6880                         /* They're not both bit variables. Is the right a literal? */
6881                         if(AOP_TYPE(right) == AOP_LIT) {
6882                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6883             
6884                         switch(size) {
6885
6886                                 case 1:
6887                                         switch(lit & 0xff) {
6888                                                 case 1:
6889                                                                 if ( IC_TRUE(ifx) ) {
6890                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6891                                                                         emitSKPNZ;
6892                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6893                                                                 } else {
6894                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6895                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6896                                                                 }
6897                                                                 break;
6898                                                 case 0xff:
6899                                                                 if ( IC_TRUE(ifx) ) {
6900                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6901                                                                         emitSKPNZ;
6902                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6903                                                                 } else {
6904                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6905                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6906                                                                 }
6907                                                                 break;
6908                                                 default:
6909                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6910                                                                 if(lit)
6911                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6912                                                                 genSkip(ifx,'z');
6913                                         } // switch lit
6914
6915
6916                                         /* end of size == 1 */
6917                                         break;
6918               
6919                                 case 2:
6920                                         genc16bit2lit(left,lit,offset);
6921                                         genSkip(ifx,'z');
6922                                         break;
6923                                         /* end of size == 2 */
6924
6925                                 default:
6926                                         /* size is 4 */
6927                                         if(lit==0) {
6928                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6929                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6930                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6931                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6932                                                 genSkip(ifx,'z');
6933                                         } else {
6934                                                 /* search for patterns that can be optimized */
6935
6936                                                 genc16bit2lit(left,lit,0);
6937                                                 lit >>= 16;
6938                                                 if(lit) {
6939                                                                 if(IC_TRUE(ifx))
6940                                                                 emitSKPZ; // if hi word unequal
6941                                                                 else
6942                                                                 emitSKPNZ; // if hi word equal
6943                                                                 // fail early
6944                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6945                                                         genc16bit2lit(left,lit,2);
6946                                                         genSkip(ifx,'z');
6947                                                 } else {
6948                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6949                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6950                                                         genSkip(ifx,'z');
6951                                                 }
6952                                         }
6953                                                 pic16_emitpLabel(falselbl->key);
6954                                                 break;
6955
6956                         } // switch size
6957           
6958                         ifx->generated = 1;
6959                         goto release ;
6960             
6961
6962           } else if(AOP_TYPE(right) == AOP_CRY ) {
6963             /* we know the left is not a bit, but that the right is */
6964             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6965             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6966                       pic16_popGet(AOP(right),offset));
6967             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6968
6969             /* if the two are equal, then W will be 0 and the Z bit is set
6970              * we could test Z now, or go ahead and check the high order bytes if
6971              * the variable we're comparing is larger than a byte. */
6972
6973             while(--size)
6974               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6975
6976             if ( IC_TRUE(ifx) ) {
6977               emitSKPNZ;
6978               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6979               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6980             } else {
6981               emitSKPZ;
6982               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6983               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6984             }
6985
6986           } else {
6987             /* They're both variables that are larger than bits */
6988             int s = size;
6989
6990             tlbl = newiTempLabel(NULL);
6991
6992             while(size--) {
6993               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6994               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6995
6996               if ( IC_TRUE(ifx) ) {
6997                 if(size) {
6998                   emitSKPZ;
6999                 
7000                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7001
7002                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7003                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7004                 } else {
7005                   emitSKPNZ;
7006
7007                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7008
7009
7010                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7011                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7012                 }
7013               } else {
7014                 emitSKPZ;
7015
7016                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7017
7018                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7020               }
7021               offset++;
7022             }
7023             if(s>1 && IC_TRUE(ifx)) {
7024               pic16_emitpLabel(tlbl->key);
7025               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7026             }
7027           }
7028         }
7029         /* mark the icode as generated */
7030         ifx->generated = 1;
7031         goto release ;
7032     }
7033
7034     /* if they are both bit variables */
7035     if (AOP_TYPE(left) == AOP_CRY &&
7036         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7037         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7038         if(AOP_TYPE(right) == AOP_LIT){
7039             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7040             if(lit == 0L){
7041                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042                 pic16_emitcode("cpl","c");
7043             } else if(lit == 1L) {
7044                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7045             } else {
7046                 pic16_emitcode("clr","c");
7047             }
7048             /* AOP_TYPE(right) == AOP_CRY */
7049         } else {
7050             symbol *lbl = newiTempLabel(NULL);
7051             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7053             pic16_emitcode("cpl","c");
7054             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7055         }
7056         /* c = 1 if egal */
7057         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7058             pic16_outBitC(result);
7059             goto release ;
7060         }
7061         if (ifx) {
7062             genIfxJump (ifx,"c");
7063             goto release ;
7064         }
7065         /* if the result is used in an arithmetic operation
7066         then put the result in place */
7067         pic16_outBitC(result);
7068     } else {
7069       
7070       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7071       gencjne(left,right,result,ifx);
7072 /*
7073       if(ifx) 
7074         gencjne(left,right,newiTempLabel(NULL));
7075       else {
7076         if(IC_TRUE(ifx)->key)
7077           gencjne(left,right,IC_TRUE(ifx)->key);
7078         else
7079           gencjne(left,right,IC_FALSE(ifx)->key);
7080         ifx->generated = 1;
7081         goto release ;
7082       }
7083       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7084         pic16_aopPut(AOP(result),"a",0);
7085         goto release ;
7086       }
7087
7088       if (ifx) {
7089         genIfxJump (ifx,"a");
7090         goto release ;
7091       }
7092 */
7093       /* if the result is used in an arithmetic operation
7094          then put the result in place */
7095 /*
7096       if (AOP_TYPE(result) != AOP_CRY) 
7097         pic16_outAcc(result);
7098 */
7099       /* leave the result in acc */
7100     }
7101
7102 release:
7103     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7105     pic16_freeAsmop(result,NULL,ic,TRUE);
7106 }
7107 #endif
7108
7109 /*-----------------------------------------------------------------*/
7110 /* ifxForOp - returns the icode containing the ifx for operand     */
7111 /*-----------------------------------------------------------------*/
7112 static iCode *ifxForOp ( operand *op, iCode *ic )
7113 {
7114   FENTRY2;
7115
7116     /* if true symbol then needs to be assigned */
7117     if (IS_TRUE_SYMOP(op))
7118         return NULL ;
7119
7120     /* if this has register type condition and
7121     the next instruction is ifx with the same operand
7122     and live to of the operand is upto the ifx only then */
7123     if (ic->next
7124         && ic->next->op == IFX
7125         && IC_COND(ic->next)->key == op->key
7126         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7127         ) {
7128                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7129           return ic->next;
7130     }
7131
7132     /*
7133     if (ic->next &&
7134         ic->next->op == IFX &&
7135         IC_COND(ic->next)->key == op->key) {
7136       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7137       return ic->next;
7138     }
7139     */
7140
7141     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7142     if (ic->next &&
7143         ic->next->op == IFX)
7144       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7145
7146     if (ic->next &&
7147         ic->next->op == IFX &&
7148         IC_COND(ic->next)->key == op->key) {
7149       DEBUGpic16_emitcode ("; "," key is okay");
7150       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7151                            OP_SYMBOL(op)->liveTo,
7152                            ic->next->seq);
7153     }
7154
7155 #if 0
7156     /* the code below is completely untested
7157      * it just allows ulong2fs.c compile -- VR */
7158          
7159     ic = ic->next;
7160     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7161                                         __FILE__, __FUNCTION__, __LINE__);
7162         
7163     /* if this has register type condition and
7164     the next instruction is ifx with the same operand
7165     and live to of the operand is upto the ifx only then */
7166     if (ic->next &&
7167         ic->next->op == IFX &&
7168         IC_COND(ic->next)->key == op->key &&
7169         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7170         return ic->next;
7171
7172     if (ic->next &&
7173         ic->next->op == IFX &&
7174         IC_COND(ic->next)->key == op->key) {
7175       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7176       return ic->next;
7177     }
7178
7179     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7180                                         __FILE__, __FUNCTION__, __LINE__);
7181
7182 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7183 #endif
7184
7185     return NULL;
7186 }
7187 /*-----------------------------------------------------------------*/
7188 /* genAndOp - for && operation                                     */
7189 /*-----------------------------------------------------------------*/
7190 static void genAndOp (iCode *ic)
7191 {
7192   operand *left,*right, *result;
7193 /*     symbol *tlbl; */
7194
7195     FENTRY;
7196
7197     /* note here that && operations that are in an
7198     if statement are taken away by backPatchLabels
7199     only those used in arthmetic operations remain */
7200     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7201     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7202     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7203
7204     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7205
7206     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7207     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7209
7210     /* if both are bit variables */
7211 /*     if (AOP_TYPE(left) == AOP_CRY && */
7212 /*         AOP_TYPE(right) == AOP_CRY ) { */
7213 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7214 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7215 /*         pic16_outBitC(result); */
7216 /*     } else { */
7217 /*         tlbl = newiTempLabel(NULL); */
7218 /*         pic16_toBoolean(left);     */
7219 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7220 /*         pic16_toBoolean(right); */
7221 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7222 /*         pic16_outBitAcc(result); */
7223 /*     } */
7224
7225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7227     pic16_freeAsmop(result,NULL,ic,TRUE);
7228 }
7229
7230
7231 /*-----------------------------------------------------------------*/
7232 /* genOrOp - for || operation                                      */
7233 /*-----------------------------------------------------------------*/
7234 /*
7235   tsd pic port -
7236   modified this code, but it doesn't appear to ever get called
7237 */
7238
7239 static void genOrOp (iCode *ic)
7240 {
7241   operand *left,*right, *result;
7242   symbol *tlbl;
7243
7244     FENTRY;  
7245
7246   /* note here that || operations that are in an
7247     if statement are taken away by backPatchLabels
7248     only those used in arthmetic operations remain */
7249     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7250     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7251     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7252
7253     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7254
7255     /* if both are bit variables */
7256     if (AOP_TYPE(left) == AOP_CRY &&
7257         AOP_TYPE(right) == AOP_CRY ) {
7258       pic16_emitcode("clrc","");
7259       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7260                AOP(left)->aopu.aop_dir,
7261                AOP(left)->aopu.aop_dir);
7262       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7263                AOP(right)->aopu.aop_dir,
7264                AOP(right)->aopu.aop_dir);
7265       pic16_emitcode("setc","");
7266
7267     } else {
7268         tlbl = newiTempLabel(NULL);
7269         pic16_toBoolean(left);
7270         emitSKPZ;
7271         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7272         pic16_toBoolean(right);
7273         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7274
7275         pic16_outBitAcc(result);
7276     }
7277
7278     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7280     pic16_freeAsmop(result,NULL,ic,TRUE);            
7281 }
7282
7283 /*-----------------------------------------------------------------*/
7284 /* isLiteralBit - test if lit == 2^n                               */
7285 /*-----------------------------------------------------------------*/
7286 static int isLiteralBit(unsigned long lit)
7287 {
7288     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7289     0x100L,0x200L,0x400L,0x800L,
7290     0x1000L,0x2000L,0x4000L,0x8000L,
7291     0x10000L,0x20000L,0x40000L,0x80000L,
7292     0x100000L,0x200000L,0x400000L,0x800000L,
7293     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7294     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7295     int idx;
7296     
7297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7298     for(idx = 0; idx < 32; idx++)
7299         if(lit == pw[idx])
7300             return idx+1;
7301     return 0;
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* continueIfTrue -                                                */
7306 /*-----------------------------------------------------------------*/
7307 static void continueIfTrue (iCode *ic)
7308 {
7309   FENTRY;
7310   if(IC_TRUE(ic))
7311     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7312   ic->generated = 1;
7313 }
7314
7315 /*-----------------------------------------------------------------*/
7316 /* jmpIfTrue -                                                     */
7317 /*-----------------------------------------------------------------*/
7318 static void jumpIfTrue (iCode *ic)
7319 {
7320   FENTRY;
7321   if(!IC_TRUE(ic))
7322     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7323   ic->generated = 1;
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* jmpTrueOrFalse -                                                */
7328 /*-----------------------------------------------------------------*/
7329 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7330 {
7331   // ugly but optimized by peephole
7332   FENTRY;
7333   if(IC_TRUE(ic)){
7334     symbol *nlbl = newiTempLabel(NULL);
7335       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7336       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7337       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7338       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7339   } else {
7340     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7341     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7342   }
7343   ic->generated = 1;
7344 }
7345
7346 /*-----------------------------------------------------------------*/
7347 /* genAnd  - code for and                                          */
7348 /*-----------------------------------------------------------------*/
7349 static void genAnd (iCode *ic, iCode *ifx)
7350 {
7351   operand *left, *right, *result;
7352   int size, offset=0;  
7353   unsigned long lit = 0L;
7354   int bytelit = 0;
7355   resolvedIfx rIfx;
7356
7357     FENTRY;
7358     
7359   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7360   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7361   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7362
7363   resolveIfx(&rIfx,ifx);
7364
7365   /* if left is a literal & right is not then exchange them */
7366   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7367       AOP_NEEDSACC(left)) {
7368     operand *tmp = right ;
7369     right = left;
7370     left = tmp;
7371   }
7372
7373   /* if result = right then exchange them */
7374   if(pic16_sameRegs(AOP(result),AOP(right))){
7375     operand *tmp = right ;
7376     right = left;
7377     left = tmp;
7378   }
7379
7380   /* if right is bit then exchange them */
7381   if (AOP_TYPE(right) == AOP_CRY &&
7382       AOP_TYPE(left) != AOP_CRY){
7383     operand *tmp = right ;
7384     right = left;
7385     left = tmp;
7386   }
7387   if(AOP_TYPE(right) == AOP_LIT)
7388     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7389
7390   size = AOP_SIZE(result);
7391
7392   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7393
7394   // if(bit & yy)
7395   // result = bit & yy;
7396   if (AOP_TYPE(left) == AOP_CRY){
7397     // c = bit & literal;
7398     if(AOP_TYPE(right) == AOP_LIT){
7399       if(lit & 1) {
7400         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7401           // no change
7402           goto release;
7403         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7404       } else {
7405         // bit(result) = 0;
7406         if(size && (AOP_TYPE(result) == AOP_CRY)){
7407           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7408           goto release;
7409         }
7410         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7411           jumpIfTrue(ifx);
7412           goto release;
7413         }
7414         pic16_emitcode("clr","c");
7415       }
7416     } else {
7417       if (AOP_TYPE(right) == AOP_CRY){
7418         // c = bit & bit;
7419         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7420         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421       } else {
7422         // c = bit & val;
7423         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7424         // c = lsb
7425         pic16_emitcode("rrc","a");
7426         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427       }
7428     }
7429     // bit = c
7430     // val = c
7431     if(size)
7432       pic16_outBitC(result);
7433     // if(bit & ...)
7434     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7435       genIfxJump(ifx, "c");           
7436     goto release ;
7437   }
7438
7439   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7440   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7441   if((AOP_TYPE(right) == AOP_LIT) &&
7442      (AOP_TYPE(result) == AOP_CRY) &&
7443      (AOP_TYPE(left) != AOP_CRY)){
7444     int posbit = isLiteralBit(lit);
7445     /* left &  2^n */
7446     if(posbit){
7447       posbit--;
7448       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7449       // bit = left & 2^n
7450       if(size)
7451         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7452       // if(left &  2^n)
7453       else{
7454         if(ifx){
7455 /*
7456           if(IC_TRUE(ifx)) {
7457             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7459           } else {
7460             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7461             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7462           }
7463 */
7464         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7465         size = AOP_SIZE(left);
7466
7467         {
7468           int bp = posbit, ofs=0;
7469           
7470             while(bp > 7) {
7471               bp -= 8;
7472               ofs++;
7473             }
7474         
7475           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7476                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7477
7478         }
7479 /*
7480           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7481                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7482 */
7483           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7484           
7485           ifx->generated = 1;
7486         }
7487         goto release;
7488       }
7489     } else {
7490       symbol *tlbl = newiTempLabel(NULL);
7491       int sizel = AOP_SIZE(left);
7492
7493       if(size)
7494         emitSETC;
7495
7496       while(sizel--) {
7497         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7498
7499           /* patch provided by Aaron Colwell */
7500           if((posbit = isLiteralBit(bytelit)) != 0) {
7501               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7502                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7503                                                 (posbit-1),0, PO_GPR_REGISTER));
7504
7505               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7506 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7507           } else {
7508               if (bytelit == 0xff) {
7509                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7510                    * a peephole could optimize it out -- VR */
7511                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512               } else {
7513                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7515               }
7516
7517               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7518                             pic16_popGetLabel(tlbl->key));
7519           }
7520         
7521 #if 0
7522           /* old code, left here for reference -- VR 09/2004 */
7523           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7524           // byte ==  2^n ?
7525           if((posbit = isLiteralBit(bytelit)) != 0)
7526             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7527           else{
7528             if(bytelit != 0x0FFL)
7529               pic16_emitcode("anl","a,%s",
7530                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7531             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7532           }
7533 #endif
7534         }
7535         offset++;
7536       }
7537       // bit = left & literal
7538       if(size) {
7539         emitCLRC;
7540         pic16_emitpLabel(tlbl->key);
7541       }
7542       // if(left & literal)
7543       else {
7544         if(ifx) {
7545           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7546           ifx->generated = 1;
7547         }
7548         pic16_emitpLabel(tlbl->key);
7549         goto release;
7550       }
7551     }
7552
7553     pic16_outBitC(result);
7554     goto release ;
7555   }
7556
7557   /* if left is same as result */
7558   if(pic16_sameRegs(AOP(result),AOP(left))){
7559     int know_W = -1;
7560     for(;size--; offset++,lit>>=8) {
7561       if(AOP_TYPE(right) == AOP_LIT){
7562         switch(lit & 0xff) {
7563         case 0x00:
7564           /*  and'ing with 0 has clears the result */
7565 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7566           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7567           break;
7568         case 0xff:
7569           /* and'ing with 0xff is a nop when the result and left are the same */
7570           break;
7571
7572         default:
7573           {
7574             int p = pic16_my_powof2( (~lit) & 0xff );
7575             if(p>=0) {
7576               /* only one bit is set in the literal, so use a bcf instruction */
7577 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7578               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7579
7580             } else {
7581               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7582               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7583               if(know_W != (lit&0xff))
7584                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7585               know_W = lit &0xff;
7586               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7587             }
7588           }    
7589         }
7590       } else {
7591         if (AOP_TYPE(left) == AOP_ACC) {
7592           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7593         } else {                    
7594           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7595           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7596
7597         }
7598       }
7599     }
7600
7601   } else {
7602     // left & result in different registers
7603     if(AOP_TYPE(result) == AOP_CRY){
7604       // result = bit
7605       // if(size), result in bit
7606       // if(!size && ifx), conditional oper: if(left & right)
7607       symbol *tlbl = newiTempLabel(NULL);
7608       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7609       if(size)
7610         pic16_emitcode("setb","c");
7611       while(sizer--){
7612         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7613         pic16_emitcode("anl","a,%s",
7614                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7615         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7616         offset++;
7617       }
7618       if(size){
7619         CLRC;
7620         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7621         pic16_outBitC(result);
7622       } else if(ifx)
7623         jmpTrueOrFalse(ifx, tlbl);
7624     } else {
7625       for(;(size--);offset++) {
7626         // normal case
7627         // result = left & right
7628         if(AOP_TYPE(right) == AOP_LIT){
7629           int t = (lit >> (offset*8)) & 0x0FFL;
7630           switch(t) { 
7631           case 0x00:
7632             pic16_emitcode("clrf","%s",
7633                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7634             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7635             break;
7636           case 0xff:
7637             pic16_emitcode("movf","%s,w",
7638                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7639             pic16_emitcode("movwf","%s",
7640                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7641             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7642             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7643             break;
7644           default:
7645             pic16_emitcode("movlw","0x%x",t);
7646             pic16_emitcode("andwf","%s,w",
7647                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7648             pic16_emitcode("movwf","%s",
7649                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7650               
7651             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7652             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7653             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7654           }
7655           continue;
7656         }
7657
7658         if (AOP_TYPE(left) == AOP_ACC) {
7659           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7661         } else {
7662           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7663           pic16_emitcode("andwf","%s,w",
7664                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7665           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7666           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7667         }
7668         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7669         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7670       }
7671     }
7672   }
7673
7674   release :
7675     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677   pic16_freeAsmop(result,NULL,ic,TRUE);     
7678 }
7679
7680 /*-----------------------------------------------------------------*/
7681 /* genOr  - code for or                                            */
7682 /*-----------------------------------------------------------------*/
7683 static void genOr (iCode *ic, iCode *ifx)
7684 {
7685     operand *left, *right, *result;
7686     int size, offset=0;
7687     unsigned long lit = 0L;
7688
7689     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7690
7691     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7692     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7693     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7694
7695     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7696
7697     /* if left is a literal & right is not then exchange them */
7698     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7699         AOP_NEEDSACC(left)) {
7700         operand *tmp = right ;
7701         right = left;
7702         left = tmp;
7703     }
7704
7705     /* if result = right then exchange them */
7706     if(pic16_sameRegs(AOP(result),AOP(right))){
7707         operand *tmp = right ;
7708         right = left;
7709         left = tmp;
7710     }
7711
7712     /* if right is bit then exchange them */
7713     if (AOP_TYPE(right) == AOP_CRY &&
7714         AOP_TYPE(left) != AOP_CRY){
7715         operand *tmp = right ;
7716         right = left;
7717         left = tmp;
7718     }
7719
7720     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7721
7722     if(AOP_TYPE(right) == AOP_LIT)
7723         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7724
7725     size = AOP_SIZE(result);
7726
7727     // if(bit | yy)
7728     // xx = bit | yy;
7729     if (AOP_TYPE(left) == AOP_CRY){
7730         if(AOP_TYPE(right) == AOP_LIT){
7731             // c = bit & literal;
7732             if(lit){
7733                 // lit != 0 => result = 1
7734                 if(AOP_TYPE(result) == AOP_CRY){
7735                   if(size)
7736                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7737                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7738                   //     AOP(result)->aopu.aop_dir,
7739                   //     AOP(result)->aopu.aop_dir);
7740                     else if(ifx)
7741                         continueIfTrue(ifx);
7742                     goto release;
7743                 }
7744             } else {
7745                 // lit == 0 => result = left
7746                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7747                     goto release;
7748                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7749             }
7750         } else {
7751             if (AOP_TYPE(right) == AOP_CRY){
7752               if(pic16_sameRegs(AOP(result),AOP(left))){
7753                 // c = bit | bit;
7754                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7755                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7756                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7757
7758                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7759                          AOP(result)->aopu.aop_dir,
7760                          AOP(result)->aopu.aop_dir);
7761                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7762                          AOP(right)->aopu.aop_dir,
7763                          AOP(right)->aopu.aop_dir);
7764                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7765                          AOP(result)->aopu.aop_dir,
7766                          AOP(result)->aopu.aop_dir);
7767               } else {
7768                 if( AOP_TYPE(result) == AOP_ACC) {
7769                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7770                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7771                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7772                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7773
7774                 } else {
7775
7776                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7777                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7778                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7779                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7780
7781                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7782                                  AOP(result)->aopu.aop_dir,
7783                                  AOP(result)->aopu.aop_dir);
7784                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7785                                  AOP(right)->aopu.aop_dir,
7786                                  AOP(right)->aopu.aop_dir);
7787                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7788                                  AOP(left)->aopu.aop_dir,
7789                                  AOP(left)->aopu.aop_dir);
7790                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7791                                  AOP(result)->aopu.aop_dir,
7792                                  AOP(result)->aopu.aop_dir);
7793                 }
7794               }
7795             } else {
7796                 // c = bit | val;
7797                 symbol *tlbl = newiTempLabel(NULL);
7798                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7799
7800
7801                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7802                 if( AOP_TYPE(right) == AOP_ACC) {
7803                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7804                   emitSKPNZ;
7805                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7806                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7807                 }
7808
7809
7810
7811                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7812                     pic16_emitcode(";XXX setb","c");
7813                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7814                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7815                 pic16_toBoolean(right);
7816                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7817                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7818                     jmpTrueOrFalse(ifx, tlbl);
7819                     goto release;
7820                 } else {
7821                     CLRC;
7822                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7823                 }
7824             }
7825         }
7826         // bit = c
7827         // val = c
7828         if(size)
7829             pic16_outBitC(result);
7830         // if(bit | ...)
7831         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832             genIfxJump(ifx, "c");           
7833         goto release ;
7834     }
7835
7836     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7837     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7838     if((AOP_TYPE(right) == AOP_LIT) &&
7839        (AOP_TYPE(result) == AOP_CRY) &&
7840        (AOP_TYPE(left) != AOP_CRY)){
7841         if(lit){
7842           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7843             // result = 1
7844             if(size)
7845                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7846             else 
7847                 continueIfTrue(ifx);
7848             goto release;
7849         } else {
7850           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851             // lit = 0, result = boolean(left)
7852             if(size)
7853                 pic16_emitcode(";XXX setb","c");
7854             pic16_toBoolean(right);
7855             if(size){
7856                 symbol *tlbl = newiTempLabel(NULL);
7857                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7858                 CLRC;
7859                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7860             } else {
7861                 genIfxJump (ifx,"a");
7862                 goto release;
7863             }
7864         }
7865         pic16_outBitC(result);
7866         goto release ;
7867     }
7868
7869     /* if left is same as result */
7870     if(pic16_sameRegs(AOP(result),AOP(left))){
7871       int know_W = -1;
7872       for(;size--; offset++,lit>>=8) {
7873         if(AOP_TYPE(right) == AOP_LIT){
7874           if((lit & 0xff) == 0)
7875             /*  or'ing with 0 has no effect */
7876             continue;
7877           else {
7878             int p = pic16_my_powof2(lit & 0xff);
7879             if(p>=0) {
7880               /* only one bit is set in the literal, so use a bsf instruction */
7881               pic16_emitpcode(POC_BSF,
7882                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7883             } else {
7884               if(know_W != (lit & 0xff))
7885                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7886               know_W = lit & 0xff;
7887               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7888             }
7889                     
7890           }
7891         } else {
7892           if (AOP_TYPE(left) == AOP_ACC) {
7893             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7894             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7895           } else {                  
7896             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7897             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7898
7899             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7901
7902           }
7903         }
7904       }
7905     } else {
7906         // left & result in different registers
7907         if(AOP_TYPE(result) == AOP_CRY){
7908             // result = bit
7909             // if(size), result in bit
7910             // if(!size && ifx), conditional oper: if(left | right)
7911             symbol *tlbl = newiTempLabel(NULL);
7912             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7913             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7914
7915
7916             if(size)
7917                 pic16_emitcode(";XXX setb","c");
7918             while(sizer--){
7919                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7920                 pic16_emitcode(";XXX orl","a,%s",
7921                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7923                 offset++;
7924             }
7925             if(size){
7926                 CLRC;
7927                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7928                 pic16_outBitC(result);
7929             } else if(ifx)
7930                 jmpTrueOrFalse(ifx, tlbl);
7931         } else for(;(size--);offset++){
7932           // normal case
7933           // result = left & right
7934           if(AOP_TYPE(right) == AOP_LIT){
7935             int t = (lit >> (offset*8)) & 0x0FFL;
7936             switch(t) { 
7937             case 0x00:
7938               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7939               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7940
7941               pic16_emitcode("movf","%s,w",
7942                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943               pic16_emitcode("movwf","%s",
7944                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945               break;
7946             default:
7947               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7948               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7949               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7950
7951               pic16_emitcode("movlw","0x%x",t);
7952               pic16_emitcode("iorwf","%s,w",
7953                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7954               pic16_emitcode("movwf","%s",
7955                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7956               
7957             }
7958             continue;
7959           }
7960
7961           // faster than result <- left, anl result,right
7962           // and better if result is SFR
7963           if (AOP_TYPE(left) == AOP_ACC) {
7964             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7965             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7966           } else {
7967             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7968             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7969
7970             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971             pic16_emitcode("iorwf","%s,w",
7972                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7973           }
7974           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7975           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7976         }
7977     }
7978
7979 release :
7980     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7982     pic16_freeAsmop(result,NULL,ic,TRUE);     
7983 }
7984
7985 /*-----------------------------------------------------------------*/
7986 /* genXor - code for xclusive or                                   */
7987 /*-----------------------------------------------------------------*/
7988 static void genXor (iCode *ic, iCode *ifx)
7989 {
7990   operand *left, *right, *result;
7991   int size, offset=0;
7992   unsigned long lit = 0L;
7993
7994   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7995
7996   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7997   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7998   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7999
8000   /* if left is a literal & right is not ||
8001      if left needs acc & right does not */
8002   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8003       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8004     operand *tmp = right ;
8005     right = left;
8006     left = tmp;
8007   }
8008
8009   /* if result = right then exchange them */
8010   if(pic16_sameRegs(AOP(result),AOP(right))){
8011     operand *tmp = right ;
8012     right = left;
8013     left = tmp;
8014   }
8015
8016   /* if right is bit then exchange them */
8017   if (AOP_TYPE(right) == AOP_CRY &&
8018       AOP_TYPE(left) != AOP_CRY){
8019     operand *tmp = right ;
8020     right = left;
8021     left = tmp;
8022   }
8023   if(AOP_TYPE(right) == AOP_LIT)
8024     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8025
8026   size = AOP_SIZE(result);
8027
8028   // if(bit ^ yy)
8029   // xx = bit ^ yy;
8030   if (AOP_TYPE(left) == AOP_CRY){
8031     if(AOP_TYPE(right) == AOP_LIT){
8032       // c = bit & literal;
8033       if(lit>>1){
8034         // lit>>1  != 0 => result = 1
8035         if(AOP_TYPE(result) == AOP_CRY){
8036           if(size)
8037             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8038             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8039           else if(ifx)
8040             continueIfTrue(ifx);
8041           goto release;
8042         }
8043         pic16_emitcode("setb","c");
8044       } else{
8045         // lit == (0 or 1)
8046         if(lit == 0){
8047           // lit == 0, result = left
8048           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8049             goto release;
8050           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8051         } else{
8052           // lit == 1, result = not(left)
8053           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8054             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8055             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8056             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8057             goto release;
8058           } else {
8059             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8060             pic16_emitcode("cpl","c");
8061           }
8062         }
8063       }
8064
8065     } else {
8066       // right != literal
8067       symbol *tlbl = newiTempLabel(NULL);
8068       if (AOP_TYPE(right) == AOP_CRY){
8069         // c = bit ^ bit;
8070         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8071       }
8072       else{
8073         int sizer = AOP_SIZE(right);
8074         // c = bit ^ val
8075         // if val>>1 != 0, result = 1
8076         pic16_emitcode("setb","c");
8077         while(sizer){
8078           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8079           if(sizer == 1)
8080             // test the msb of the lsb
8081             pic16_emitcode("anl","a,#0xfe");
8082           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8083           sizer--;
8084         }
8085         // val = (0,1)
8086         pic16_emitcode("rrc","a");
8087       }
8088       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8089       pic16_emitcode("cpl","c");
8090       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8091     }
8092     // bit = c
8093     // val = c
8094     if(size)
8095       pic16_outBitC(result);
8096     // if(bit | ...)
8097     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8098       genIfxJump(ifx, "c");           
8099     goto release ;
8100   }
8101
8102   if(pic16_sameRegs(AOP(result),AOP(left))){
8103     /* if left is same as result */
8104     for(;size--; offset++) {
8105       if(AOP_TYPE(right) == AOP_LIT){
8106         int t  = (lit >> (offset*8)) & 0x0FFL;
8107         if(t == 0x00L)
8108           continue;
8109         else
8110           if (IS_AOP_PREG(left)) {
8111             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8113             pic16_aopPut(AOP(result),"a",offset);
8114           } else {
8115             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117             pic16_emitcode("xrl","%s,%s",
8118                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8119                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8120           }
8121       } else {
8122         if (AOP_TYPE(left) == AOP_ACC)
8123           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124         else {
8125           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8126           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8127 /*
8128           if (IS_AOP_PREG(left)) {
8129             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8130             pic16_aopPut(AOP(result),"a",offset);
8131           } else
8132             pic16_emitcode("xrl","%s,a",
8133                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134 */
8135         }
8136       }
8137     }
8138   } else {
8139     // left & result in different registers
8140     if(AOP_TYPE(result) == AOP_CRY){
8141       // result = bit
8142       // if(size), result in bit
8143       // if(!size && ifx), conditional oper: if(left ^ right)
8144       symbol *tlbl = newiTempLabel(NULL);
8145       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8146       if(size)
8147         pic16_emitcode("setb","c");
8148       while(sizer--){
8149         if((AOP_TYPE(right) == AOP_LIT) &&
8150            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8151           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152         } else {
8153           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154           pic16_emitcode("xrl","a,%s",
8155                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156         }
8157         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8158         offset++;
8159       }
8160       if(size){
8161         CLRC;
8162         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8163         pic16_outBitC(result);
8164       } else if(ifx)
8165         jmpTrueOrFalse(ifx, tlbl);
8166     } else for(;(size--);offset++){
8167       // normal case
8168       // result = left & right
8169       if(AOP_TYPE(right) == AOP_LIT){
8170         int t = (lit >> (offset*8)) & 0x0FFL;
8171         switch(t) { 
8172         case 0x00:
8173           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8174           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8175           pic16_emitcode("movf","%s,w",
8176                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177           pic16_emitcode("movwf","%s",
8178                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8179           break;
8180         case 0xff:
8181           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8182           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8183           pic16_emitcode("comf","%s,w",
8184                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185           pic16_emitcode("movwf","%s",
8186                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187           break;
8188         default:
8189           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8190           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8191           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8192           pic16_emitcode("movlw","0x%x",t);
8193           pic16_emitcode("xorwf","%s,w",
8194                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195           pic16_emitcode("movwf","%s",
8196                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8197
8198         }
8199         continue;
8200       }
8201
8202       // faster than result <- left, anl result,right
8203       // and better if result is SFR
8204       if (AOP_TYPE(left) == AOP_ACC) {
8205         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8206         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8207       } else {
8208         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8209         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8212       }
8213       if ( AOP_TYPE(result) != AOP_ACC){
8214         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8215         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8216       }
8217     }
8218   }
8219
8220   release :
8221     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8223   pic16_freeAsmop(result,NULL,ic,TRUE);     
8224 }
8225
8226 /*-----------------------------------------------------------------*/
8227 /* genInline - write the inline code out                           */
8228 /*-----------------------------------------------------------------*/
8229 static void genInline (iCode *ic)
8230 {
8231   char *buffer, *bp, *bp1;
8232     
8233         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8234
8235         _G.inLine += (!options.asmpeep);
8236
8237         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8238         strcpy(buffer,IC_INLINE(ic));
8239         
8240         while((bp1=strstr(bp, "\\n"))) {
8241           *bp1++ = '\n';
8242           *bp1++ = ' ';
8243           bp = bp1;
8244         }
8245         bp = bp1 = buffer;
8246
8247 #if 0
8248   /* This is an experimental code for #pragma inline
8249      and is temporarily disabled for 2.5.0 release */
8250         if(asmInlineMap)
8251         {
8252           symbol *sym;
8253           char *s;
8254           char *cbuf;
8255           int cblen;
8256
8257             cbuf = Safe_strdup(buffer);
8258             cblen = strlen(buffer)+1;
8259             memset(cbuf, 0, cblen);
8260
8261             bp = buffer;
8262             bp1 = cbuf;
8263             while(*bp) {
8264               if(*bp != '%')*bp1++ = *bp++;
8265               else {
8266                 int i;
8267
8268                   bp++;
8269                   i = *bp - '0';
8270                   if(i>elementsInSet(asmInlineMap))break;
8271                   
8272                   bp++;
8273                   s = indexSet(asmInlineMap, i);
8274                   DEBUGpc("searching symbol s = `%s'", s);
8275                   sym = findSym(SymbolTab, NULL, s);
8276
8277                   if(sym->reqv) {
8278                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8279                   } else {
8280                     strcat(bp1, sym->rname);
8281                   }
8282                   
8283                   while(*bp1)bp1++;
8284               }
8285               
8286               if(strlen(bp1) > cblen - 16) {
8287                 int i = strlen(cbuf);
8288                 cblen += 50;
8289                 cbuf = realloc(cbuf, cblen);
8290                 memset(cbuf+i, 0, 50);
8291                 bp1 = cbuf + i;
8292               }
8293             }
8294             
8295             free(buffer);
8296             buffer = Safe_strdup( cbuf );
8297             free(cbuf);
8298             
8299             bp = bp1 = buffer;
8300         }
8301 #endif  /* 0 */
8302
8303         /* emit each line as a code */
8304         while (*bp) {
8305                 if (*bp == '\n') {
8306                         *bp++ = '\0';
8307
8308                         if(*bp1)
8309                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8310                         bp1 = bp;
8311                 } else {
8312                         if (*bp == ':') {
8313                                 bp++;
8314                                 *bp = '\0';
8315                                 bp++;
8316
8317                                 /* print label, use this special format with NULL directive
8318                                  * to denote that the argument should not be indented with tab */
8319                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8320                                 bp1 = bp;
8321                         } else
8322                                 bp++;
8323                 }
8324         }
8325
8326         if ((bp1 != bp) && *bp1)
8327                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8328
8329
8330     Safe_free(buffer);
8331
8332     _G.inLine -= (!options.asmpeep);
8333 }
8334
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry                                */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8339 {
8340   operand *left , *result ;
8341   int size, offset = 0, same;
8342
8343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344
8345   /* rotate right with carry */
8346   left = IC_LEFT(ic);
8347   result=IC_RESULT(ic);
8348   pic16_aopOp (left,ic,FALSE);
8349   pic16_aopOp (result,ic,TRUE);
8350
8351   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8352
8353   same = pic16_sameRegs(AOP(result),AOP(left));
8354
8355   size = AOP_SIZE(result);    
8356
8357   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8358
8359   /* get the lsb and put it into the carry */
8360   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8361
8362   offset = 0 ;
8363
8364   while(size--) {
8365
8366     if(same) {
8367       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8368     } else {
8369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8371     }
8372
8373     offset++;
8374   }
8375
8376   pic16_freeAsmop(left,NULL,ic,TRUE);
8377   pic16_freeAsmop(result,NULL,ic,TRUE);
8378 }
8379
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry               */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8384 {    
8385   operand *left , *result ;
8386   int size, offset = 0;
8387   int same;
8388
8389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8390   /* rotate right with carry */
8391   left = IC_LEFT(ic);
8392   result=IC_RESULT(ic);
8393   pic16_aopOp (left,ic,FALSE);
8394   pic16_aopOp (result,ic,TRUE);
8395
8396   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8397
8398   same = pic16_sameRegs(AOP(result),AOP(left));
8399
8400   /* move it to the result */
8401   size = AOP_SIZE(result);    
8402
8403   /* get the msb and put it into the carry */
8404   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8405
8406   offset = 0 ;
8407
8408   while(size--) {
8409
8410     if(same) {
8411       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8412     } else {
8413       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8415     }
8416
8417     offset++;
8418   }
8419
8420
8421   pic16_freeAsmop(left,NULL,ic,TRUE);
8422   pic16_freeAsmop(result,NULL,ic,TRUE);
8423 }
8424
8425
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427  * so the following probably is not needed -- VR */
8428  
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit               */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8433 {
8434     operand *left, *result;
8435     left = IC_LEFT(ic);
8436     result=IC_RESULT(ic);
8437     pic16_aopOp (left,ic,FALSE);
8438     pic16_aopOp (result,ic,FALSE);
8439
8440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441     /* get the highest order byte into a */
8442     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443     if(AOP_TYPE(result) == AOP_CRY){
8444         pic16_emitcode("rlc","a");
8445         pic16_outBitC(result);
8446     }
8447     else{
8448         pic16_emitcode("rl","a");
8449         pic16_emitcode("anl","a,#0x01");
8450         pic16_outAcc(result);
8451     }
8452
8453
8454     pic16_freeAsmop(left,NULL,ic,TRUE);
8455     pic16_freeAsmop(result,NULL,ic,TRUE);
8456 }
8457
8458 #if 0
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count                 */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8463 {
8464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8465     shCount &= 0x0007;              // shCount : 0..7
8466     switch(shCount){
8467         case 0 :
8468             break;
8469         case 1 :
8470             pic16_emitcode("rl","a");
8471             break;
8472         case 2 :
8473             pic16_emitcode("rl","a");
8474             pic16_emitcode("rl","a");
8475             break;
8476         case 3 :
8477             pic16_emitcode("swap","a");
8478             pic16_emitcode("rr","a");
8479             break;
8480         case 4 :
8481             pic16_emitcode("swap","a");
8482             break;
8483         case 5 :
8484             pic16_emitcode("swap","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 6 :
8488             pic16_emitcode("rr","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 7 :
8492             pic16_emitcode("rr","a");
8493             break;
8494     }
8495 }
8496 #endif
8497
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count                  */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8502 {
8503         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8504         switch(shCount){
8505                 case 0 :
8506                         return;
8507                         break;
8508                 case 1 :
8509                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 2 :
8512                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514                         break;
8515                 case 3 :
8516                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         break;
8519                 case 4 :
8520                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 5 :
8523                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 6 :
8527                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 7 :
8531                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533         }
8534
8535         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8536 }
8537
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count                 */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8542 {
8543         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8544         switch(shCount){
8545                 case 0 :
8546                         return; break;
8547                 case 1 :
8548                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 2 :
8551                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 3 :
8555                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 4 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 5 :
8562                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 6 :
8566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 7 :
8570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         break;
8572         }
8573         
8574         if(andmask)
8575                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8576         else
8577                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8578 }
8579
8580 #if 0
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count                 */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8585 {
8586     symbol *tlbl ;
8587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8588     if(shCount != 0){
8589         if(shCount == 1){
8590             pic16_emitcode("mov","c,acc.7");
8591             pic16_emitcode("rrc","a");
8592         } else if(shCount == 2){
8593             pic16_emitcode("mov","c,acc.7");
8594             pic16_emitcode("rrc","a");
8595             pic16_emitcode("mov","c,acc.7");
8596             pic16_emitcode("rrc","a");
8597         } else {
8598             tlbl = newiTempLabel(NULL);
8599             /* rotate right accumulator */
8600             AccRol(8 - shCount);
8601             /* and kill the higher order bits */
8602             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604             pic16_emitcode("orl","a,#0x%02x",
8605                      (unsigned char)~SRMask[shCount]);
8606             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8607         }
8608     }
8609 }
8610 #endif
8611
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result   */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616                                 operand *result, int offr,
8617                                 int shCount)
8618 {
8619   int same;
8620
8621   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8622
8623   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8624
8625   switch(shCount) {
8626   case 1:
8627     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8628     if(same) 
8629       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8630     else {
8631       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8633     }
8634
8635     break;
8636   case 2:
8637
8638     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8639     if(same) 
8640       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8641     else {
8642       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8644     }
8645     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8647
8648     break;
8649
8650   case 3:
8651     if(same)
8652       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8653     else {
8654       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8656     }
8657
8658     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8659     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8660     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8661
8662     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8664
8665     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666     break;
8667
8668   case 4:
8669     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8671     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8673     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8674     break;
8675   case 5:
8676     if(same) {
8677       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8678     } else {
8679       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8680       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8681     }
8682     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688
8689   case 6:
8690     if(same) {
8691       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697     } else {
8698       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8699       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8701       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8703     }
8704     break;
8705
8706   case 7:
8707     if(same) {
8708       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712     } else {
8713       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8716     }
8717
8718   default:
8719     break;
8720   }
8721 }
8722
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result   */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727                                 operand *result, int offr,
8728                                 int shCount, int sign)
8729 {
8730   int same;
8731
8732   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8733
8734   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8735
8736   /* Copy the msb into the carry if signed. */
8737   if(sign) {
8738     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8739     return;
8740   }
8741
8742
8743
8744   switch(shCount) {
8745   case 1:
8746     emitCLRC;
8747     if(same) 
8748       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8749     else {
8750       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8752     }
8753     break;
8754   case 2:
8755     emitCLRC;
8756     if(same) {
8757       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758     } else {
8759       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761     }
8762     emitCLRC;
8763     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8764
8765     break;
8766   case 3:
8767     if(same)
8768       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8769     else {
8770       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     }
8773
8774     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8775     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8776     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8777     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     break;
8779       
8780   case 4:
8781     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8783     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8784     break;
8785
8786   case 5:
8787     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790     //emitCLRC;
8791     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8792
8793     break;
8794   case 6:
8795
8796     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8797     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8800     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8801     break;
8802
8803   case 7:
8804
8805     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8808
8809     break;
8810
8811   default:
8812     break;
8813   }
8814 }
8815
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result    */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820                                 operand *result, int offr, int shCount)
8821 {
8822   int same;
8823
8824   //    char *l;
8825   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8826
8827   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8829     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8830     //    MOVA(l);
8831     /* shift left accumulator */
8832     //AccLsh(shCount); // don't comment out just yet...
8833   //    pic16_aopPut(AOP(result),"a",offr);
8834
8835   switch(shCount) {
8836   case 1:
8837     /* Shift left 1 bit position */
8838     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839     if(same) {
8840       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8841     } else {
8842       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844     }
8845     break;
8846   case 2:
8847     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851     break;
8852   case 3:
8853     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8858     break;
8859   case 4:
8860     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     break;
8864   case 5:
8865     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869     break;
8870   case 6:
8871     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8876     break;
8877   case 7:
8878     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8881     break;
8882
8883   default:
8884     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8885   }
8886
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result                  */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893                             operand *result, int offr)
8894 {
8895   char *l;
8896   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8897   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8899
8900     if (*l == '@' && (IS_AOP_PREG(result))) {
8901       pic16_emitcode("mov","a,%s",l);
8902       pic16_aopPut(AOP(result),"a",offr);
8903     } else {
8904       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906     }
8907   }
8908 }
8909
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result   */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914                                 operand *result, int offr, int shCount)
8915 {
8916   int same = pic16_sameRegs(AOP(result), AOP(left));
8917   int i;
8918
8919   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8920
8921   if (same && (offl != offr)) { // shift bytes
8922     if (offr > offl) {
8923        for(i=1;i>-1;i--) {
8924          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8926        }
8927     } else { // just treat as different later on
8928                 same = 0;
8929     }
8930   }
8931
8932   if(same) {
8933     switch(shCount) {
8934     case 0:
8935       break;
8936     case 1:
8937     case 2:
8938     case 3:
8939
8940       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8943
8944       while(--shCount) {
8945                 emitCLRC;
8946                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8948       }
8949
8950       break;
8951     case 4:
8952     case 5:
8953       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8960       if(shCount >=5) {
8961                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8963       }
8964       break;
8965     case 6:
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976       break;
8977     case 7:
8978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983     }
8984
8985   } else {
8986     switch(shCount) {
8987     case 0:
8988       break;
8989     case 1:
8990     case 2:
8991     case 3:
8992       /* note, use a mov/add for the shift since the mov has a
8993          chance of getting optimized out */
8994       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8998       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8999
9000       while(--shCount) {
9001                 emitCLRC;
9002                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9004       }
9005       break;
9006
9007     case 4:
9008     case 5:
9009       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9017
9018
9019       if(shCount == 5) {
9020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022       }
9023       break;
9024     case 6:
9025       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9029
9030       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038       break;
9039     case 7:
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045     }
9046   }
9047
9048 }
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result  */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053                                 operand *result, int offr,
9054                                 int shCount, int sign)
9055 {
9056   int same = pic16_sameRegs(AOP(result), AOP(left));
9057   int i;
9058   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9059
9060   if (same && (offl != offr)) { // shift right bytes
9061     if (offr < offl) {
9062        for(i=0;i<2;i++) {
9063          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9065        }
9066     } else { // just treat as different later on
9067                 same = 0;
9068     }
9069   }
9070
9071   switch(shCount) {
9072   case 0:
9073     break;
9074   case 1:
9075   case 2:
9076   case 3:
9077     if(sign)
9078       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9079     else
9080       emitCLRC;
9081
9082     if(same) {
9083       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9085     } else {
9086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9090     }
9091
9092     while(--shCount) {
9093       if(sign)
9094                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9095       else
9096                 emitCLRC;
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099     }
9100     break;
9101   case 4:
9102   case 5:
9103     if(same) {
9104
9105       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9108
9109       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9113     } else {
9114       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9117
9118       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9123     }
9124
9125     if(shCount >=5) {
9126       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9128     }
9129
9130     if(sign) {
9131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132       pic16_emitpcode(POC_BTFSC, 
9133                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9135     }
9136
9137     break;
9138
9139   case 6:
9140     if(same) {
9141
9142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9144
9145       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9146       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9149       if(sign) {
9150         pic16_emitpcode(POC_BTFSC, 
9151                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9153       }
9154       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158     } else {
9159       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9164       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9165       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9167       if(sign) {
9168         pic16_emitpcode(POC_BTFSC, 
9169                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9171       }
9172       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9174
9175         
9176     }
9177
9178     break;
9179   case 7:
9180     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9184     if(sign) {
9185       emitSKPNC;
9186       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9187     } else 
9188       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9189   }
9190 }
9191
9192
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197                                 operand *result, int offr, int shCount)
9198 {
9199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9200
9201     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202     /* shift left accumulator */
9203     AccLsh(shCount);
9204     /* or with result */
9205     /* back to result */
9206     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9207 }
9208
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213                                 operand *result, int offr, int shCount)
9214 {
9215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9216     
9217     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218     /* shift right accumulator */
9219     AccRsh(shCount, 1);
9220     /* or with result */
9221     /* back to result */
9222     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count       */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9229 {       
9230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9232 }
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0           */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9238 {
9239     int size;
9240     
9241     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242     size = pic16_getDataSize(result);
9243
9244     /* if shCount >= 8 */
9245     if (shCount >= 8) {
9246         shCount -= 8 ;
9247
9248         if (size > 1){
9249             if (shCount)
9250                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9251             else 
9252                 movLeft2Result(left, LSB, result, MSB16);
9253         }
9254         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9255     }
9256
9257     /*  1 <= shCount <= 7 */
9258     else {  
9259         if(size == 1)
9260             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9261         else 
9262             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9263     }
9264 }
9265
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result            */
9268 /* offr = LSB or MSB16                                             */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9271 {
9272     int size = AOP_SIZE(result);
9273     int same = pic16_sameRegs(AOP(left),AOP(result));
9274         int i;
9275
9276     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9277
9278         if (same && (offr == MSB16)) { //shift one byte
9279                 for(i=size-1;i>=MSB16;i--) {
9280                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9282                 }
9283         } else {
9284                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9285         }
9286         
9287     if (size > LSB+offr ){
9288                 if (same) {
9289                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9290                 } else {
9291                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9293                 }
9294          }
9295
9296     if(size > MSB16+offr){
9297                 if (same) {
9298                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9299                 } else {
9300                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9302                 }
9303     }
9304
9305     if(size > MSB24+offr){
9306                 if (same) {
9307                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9308                 } else {
9309                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9311                 }
9312     }
9313
9314     if(size > MSB32+offr){
9315                 if (same) {
9316                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9317                 } else {
9318                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9320                 }
9321     }
9322     if(offr != LSB)
9323                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9324
9325 }
9326
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0             */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9331 {
9332     int size;
9333
9334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9335     size = AOP_SIZE(result);
9336
9337     /* if shifting more that 3 bytes */
9338     if (shCount >= 24 ) {
9339         shCount -= 24;
9340         if (shCount)
9341             /* lowest order of left goes to the highest
9342             order of the destination */
9343             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9344         else
9345             movLeft2Result(left, LSB, result, MSB32);
9346
9347                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9350
9351         return;
9352     }
9353
9354     /* more than two bytes */
9355     else if ( shCount >= 16 ) {
9356         /* lower order two bytes goes to higher order two bytes */
9357         shCount -= 16;
9358         /* if some more remaining */
9359         if (shCount)
9360             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9361         else {
9362             movLeft2Result(left, MSB16, result, MSB32);
9363             movLeft2Result(left, LSB, result, MSB24);
9364         }
9365                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9367         return;
9368     }    
9369
9370     /* if more than 1 byte */
9371     else if ( shCount >= 8 ) {
9372         /* lower order three bytes goes to higher order  three bytes */
9373         shCount -= 8;
9374         if(size == 2){
9375             if(shCount)
9376                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9377             else
9378                 movLeft2Result(left, LSB, result, MSB16);
9379         }
9380         else{   /* size = 4 */
9381             if(shCount == 0){
9382                 movLeft2Result(left, MSB24, result, MSB32);
9383                 movLeft2Result(left, MSB16, result, MSB24);
9384                 movLeft2Result(left, LSB, result, MSB16);
9385                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386             }
9387             else if(shCount == 1)
9388                 shiftLLong(left, result, MSB16);
9389             else{
9390                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9394             }
9395         }
9396     }
9397
9398     /* 1 <= shCount <= 7 */
9399     else if(shCount <= 3)
9400     { 
9401         shiftLLong(left, result, LSB);
9402         while(--shCount >= 1)
9403             shiftLLong(result, result, LSB);
9404     }
9405     /* 3 <= shCount <= 7, optimize */
9406     else{
9407         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9410     }
9411 }
9412
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count              */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9417                                  operand *right,
9418                                  operand *result,
9419                                  iCode *ic)
9420 {    
9421     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9422     int size;
9423
9424     FENTRY;
9425     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426     pic16_freeAsmop(right,NULL,ic,TRUE);
9427
9428     pic16_aopOp(left,ic,FALSE);
9429     pic16_aopOp(result,ic,TRUE);
9430
9431     size = getSize(operandType(result));
9432
9433 #if VIEW_SIZE
9434     pic16_emitcode("; shift left ","result %d, left %d",size,
9435              AOP_SIZE(left));
9436 #endif
9437
9438     /* I suppose that the left size >= result size */
9439     if(shCount == 0){
9440         while(size--){
9441             movLeft2Result(left, size, result, size);
9442         }
9443     }
9444
9445     else if(shCount >= (size * 8))
9446         while(size--)
9447             pic16_aopPut(AOP(result),zero,size);
9448     else{
9449         switch (size) {
9450             case 1:
9451                 genlshOne (result,left,shCount);
9452                 break;
9453
9454             case 2:
9455             case 3:
9456                 genlshTwo (result,left,shCount);
9457                 break;
9458
9459             case 4:
9460                 genlshFour (result,left,shCount);
9461                 break;
9462         }
9463     }
9464     pic16_freeAsmop(left,NULL,ic,TRUE);
9465     pic16_freeAsmop(result,NULL,ic,TRUE);
9466 }
9467
9468 /*-----------------------------------------------------------------*
9469  * genMultiAsm - repeat assembly instruction for size of register.
9470  * if endian == 1, then the high byte (i.e base address + size of 
9471  * register) is used first else the low byte is used first;
9472  *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9474 {
9475
9476   int offset = 0;
9477
9478   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9479
9480   if(!reg)
9481     return;
9482
9483   if(!endian) {
9484     endian = 1;
9485   } else {
9486     endian = -1;
9487     offset = size-1;
9488   }
9489
9490   while(size--) {
9491     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9492     offset += endian;
9493   }
9494
9495 }
9496
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting                 */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9502 {
9503   operand *left,*right, *result;
9504   int size, offset;
9505 //  char *l;
9506   symbol *tlbl , *tlbl1;
9507   pCodeOp *pctemp;
9508
9509   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9510
9511   right = IC_RIGHT(ic);
9512   left  = IC_LEFT(ic);
9513   result = IC_RESULT(ic);
9514
9515   pic16_aopOp(right,ic,FALSE);
9516
9517   /* if the shift count is known then do it 
9518      as efficiently as possible */
9519   if (AOP_TYPE(right) == AOP_LIT) {
9520     pic16_genLeftShiftLiteral (left,right,result,ic);
9521     return ;
9522   }
9523
9524   /* shift count is unknown then we have to form
9525    * a loop. Get the loop count in WREG : Note: we take
9526    * only the lower order byte since shifting
9527    * more than 32 bits make no sense anyway, ( the
9528    * largest size of an object can be only 32 bits ) */
9529   
9530   pic16_aopOp(left,ic,FALSE);
9531   pic16_aopOp(result,ic,FALSE);
9532
9533   /* now move the left to the result if they are not the
9534    * same, and if size > 1,
9535    * and if right is not same to result (!!!) -- VR */
9536   if (!pic16_sameRegs(AOP(left),AOP(result))
9537       && (AOP_SIZE(result) > 1)) {
9538
9539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540
9541     size = AOP_SIZE(result);
9542     offset=0;
9543     while (size--) {
9544
9545 #if 0
9546       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547       if (*l == '@' && (IS_AOP_PREG(result))) {
9548
9549           pic16_emitcode("mov","a,%s",l);
9550           pic16_aopPut(AOP(result),"a",offset);
9551       } else
9552 #endif
9553       {
9554         /* we don't know if left is a literal or a register, take care -- VR */
9555         pic16_mov2f(AOP(result), AOP(left), offset);
9556       }
9557       offset++;
9558     }
9559   }
9560
9561   size = AOP_SIZE(result);
9562
9563   /* if it is only one byte then */
9564   if (size == 1) {
9565     if(optimized_for_speed) {
9566       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9568       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9570       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9573       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9574       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9575       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9576       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9578     } else {
9579
9580       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9581
9582       tlbl = newiTempLabel(NULL);
9583
9584 #if 1
9585       /* this is already done, why change it? */
9586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587                 pic16_mov2f(AOP(result), AOP(left), 0);
9588       }
9589 #endif
9590
9591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9592       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9593       pic16_emitpLabel(tlbl->key);
9594       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9596       emitSKPC;
9597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9598     }
9599     goto release ;
9600   }
9601     
9602   if (pic16_sameRegs(AOP(left),AOP(result))) {
9603
9604     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9605     
9606     tlbl = newiTempLabel(NULL);
9607     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9608     genMultiAsm(POC_RRCF, result, size,1);
9609     pic16_emitpLabel(tlbl->key);
9610     genMultiAsm(POC_RLCF, result, size,0);
9611     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9612     emitSKPC;
9613     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9614     goto release;
9615   }
9616
9617   //tlbl = newiTempLabel(NULL);
9618   //offset = 0 ;   
9619   //tlbl1 = newiTempLabel(NULL);
9620
9621   //reAdjustPreg(AOP(result));    
9622     
9623   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9624   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9625   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9626   //MOVA(l);
9627   //pic16_emitcode("add","a,acc");         
9628   //pic16_aopPut(AOP(result),"a",offset++);
9629   //while (--size) {
9630   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631   //  MOVA(l);
9632   //  pic16_emitcode("rlc","a");         
9633   //  pic16_aopPut(AOP(result),"a",offset++);
9634   //}
9635   //reAdjustPreg(AOP(result));
9636
9637   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9639
9640
9641   tlbl = newiTempLabel(NULL);
9642   tlbl1= newiTempLabel(NULL);
9643
9644   size = AOP_SIZE(result);
9645   offset = 1;
9646
9647   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9648
9649   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9650
9651   /* offset should be 0, 1 or 3 */
9652   
9653   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9654   emitSKPNZ;
9655   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9656
9657   pic16_emitpcode(POC_MOVWF, pctemp);
9658
9659
9660   pic16_emitpLabel(tlbl->key);
9661
9662   emitCLRC;
9663   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9664   while(--size)
9665     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9666
9667   pic16_emitpcode(POC_DECFSZ,  pctemp);
9668   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669   pic16_emitpLabel(tlbl1->key);
9670
9671   pic16_popReleaseTempReg(pctemp,1);
9672
9673
9674  release:
9675   pic16_freeAsmop (right,NULL,ic,TRUE);
9676   pic16_freeAsmop(left,NULL,ic,TRUE);
9677   pic16_freeAsmop(result,NULL,ic,TRUE);
9678 }
9679 #endif
9680
9681
9682 #if 0
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting                 */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9688 {
9689   operand *left,*right, *result;
9690   int size, offset;
9691   char *l;
9692   symbol *tlbl , *tlbl1;
9693   pCodeOp *pctemp;
9694
9695   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9696
9697   right = IC_RIGHT(ic);
9698   left  = IC_LEFT(ic);
9699   result = IC_RESULT(ic);
9700
9701   pic16_aopOp(right,ic,FALSE);
9702
9703   /* if the shift count is known then do it 
9704      as efficiently as possible */
9705   if (AOP_TYPE(right) == AOP_LIT) {
9706     pic16_genLeftShiftLiteral (left,right,result,ic);
9707     return ;
9708   }
9709
9710   /* shift count is unknown then we have to form 
9711      a loop get the loop count in B : Note: we take
9712      only the lower order byte since shifting
9713      more that 32 bits make no sense anyway, ( the
9714      largest size of an object can be only 32 bits ) */  
9715
9716     
9717   pic16_aopOp(left,ic,FALSE);
9718   pic16_aopOp(result,ic,FALSE);
9719
9720   /* now move the left to the result if they are not the
9721      same */
9722   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9723       AOP_SIZE(result) > 1) {
9724
9725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9726
9727     size = AOP_SIZE(result);
9728     offset=0;
9729     while (size--) {
9730       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731       if (*l == '@' && (IS_AOP_PREG(result))) {
9732
9733         pic16_emitcode("mov","a,%s",l);
9734         pic16_aopPut(AOP(result),"a",offset);
9735       } else {
9736
9737         /* we don't know if left is a literal or a register, take care -- VR */
9738         pic16_mov2f(AOP(result), AOP(left), offset);
9739       }
9740       offset++;
9741     }
9742   }
9743
9744   size = AOP_SIZE(result);
9745
9746   /* if it is only one byte then */
9747   if (size == 1) {
9748     if(optimized_for_speed) {
9749       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9751       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9753       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9754       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9756       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9757       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9758       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9759       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9761     } else {
9762
9763       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9764
9765       tlbl = newiTempLabel(NULL);
9766       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767                 pic16_mov2f(AOP(result), AOP(left), 0);
9768                 
9769 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9770 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9771       }
9772
9773       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9774       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9775       pic16_emitpLabel(tlbl->key);
9776       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9777       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9778       emitSKPC;
9779       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9780     }
9781     goto release ;
9782   }
9783     
9784   if (pic16_sameRegs(AOP(left),AOP(result))) {
9785
9786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9787     
9788     tlbl = newiTempLabel(NULL);
9789     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9790     genMultiAsm(POC_RRCF, result, size,1);
9791     pic16_emitpLabel(tlbl->key);
9792     genMultiAsm(POC_RLCF, result, size,0);
9793     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9794     emitSKPC;
9795     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796     goto release;
9797   }
9798
9799   //tlbl = newiTempLabel(NULL);
9800   //offset = 0 ;   
9801   //tlbl1 = newiTempLabel(NULL);
9802
9803   //reAdjustPreg(AOP(result));    
9804     
9805   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9806   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9807   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9808   //MOVA(l);
9809   //pic16_emitcode("add","a,acc");         
9810   //pic16_aopPut(AOP(result),"a",offset++);
9811   //while (--size) {
9812   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813   //  MOVA(l);
9814   //  pic16_emitcode("rlc","a");         
9815   //  pic16_aopPut(AOP(result),"a",offset++);
9816   //}
9817   //reAdjustPreg(AOP(result));
9818
9819   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9821
9822
9823   tlbl = newiTempLabel(NULL);
9824   tlbl1= newiTempLabel(NULL);
9825
9826   size = AOP_SIZE(result);
9827   offset = 1;
9828
9829   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9830
9831   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9832
9833   /* offset should be 0, 1 or 3 */
9834   
9835   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9836   emitSKPNZ;
9837   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9838
9839   pic16_emitpcode(POC_MOVWF, pctemp);
9840
9841
9842   pic16_emitpLabel(tlbl->key);
9843
9844   emitCLRC;
9845   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9846   while(--size)
9847     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9848
9849   pic16_emitpcode(POC_DECFSZ,  pctemp);
9850   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851   pic16_emitpLabel(tlbl1->key);
9852
9853   pic16_popReleaseTempReg(pctemp,1);
9854
9855
9856  release:
9857   pic16_freeAsmop (right,NULL,ic,TRUE);
9858   pic16_freeAsmop(left,NULL,ic,TRUE);
9859   pic16_freeAsmop(result,NULL,ic,TRUE);
9860 }
9861 #endif
9862
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count      */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867                        int shCount, int sign)
9868 {
9869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9871 }
9872
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0          */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877                        int shCount, int sign)
9878 {
9879   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880   /* if shCount >= 8 */
9881   if (shCount >= 8) {
9882     shCount -= 8 ;
9883     if (shCount)
9884       shiftR1Left2Result(left, MSB16, result, LSB,
9885                          shCount, sign);
9886     else
9887       movLeft2Result(left, MSB16, result, LSB);
9888
9889     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9890
9891     if(sign) {
9892       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9893       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
9894     }
9895   }
9896
9897   /*  1 <= shCount <= 7 */
9898   else
9899     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9900 }
9901
9902 /*-----------------------------------------------------------------*/
9903 /* shiftRLong - shift right one long from left to result           */
9904 /* offl = LSB or MSB16                                             */
9905 /*-----------------------------------------------------------------*/
9906 static void shiftRLong (operand *left, int offl,
9907                         operand *result, int sign)
9908 {
9909     int size = AOP_SIZE(result);
9910     int same = pic16_sameRegs(AOP(left),AOP(result));
9911     int i;
9912     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9913
9914         if (same && (offl == MSB16)) { //shift one byte right
9915                 for(i=MSB16;i<size;i++) {
9916                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9917                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9918                 }
9919         }
9920
9921     if(sign)
9922                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9923         else
9924                 emitCLRC;
9925
9926         if (same) {
9927                 if (offl == LSB)
9928                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9929         } else {
9930         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9931         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9932         }
9933
9934     if(offl == MSB16) {
9935         /* add sign of "a" */
9936         pic16_addSign(result, MSB32, sign);
9937         }
9938
9939         if (same) {
9940         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9941         } else {
9942         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9943         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9944         }
9945         
9946         if (same) {
9947         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9948         } else {
9949         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9950         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9951         }
9952
9953         if (same) {
9954         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9955         } else {
9956         if(offl == LSB){
9957                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9958                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9959         }
9960         }
9961 }
9962
9963 /*-----------------------------------------------------------------*/
9964 /* genrshFour - shift four byte by a known amount != 0             */
9965 /*-----------------------------------------------------------------*/
9966 static void genrshFour (operand *result, operand *left,
9967                         int shCount, int sign)
9968 {
9969   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9970   /* if shifting more that 3 bytes */
9971   if(shCount >= 24 ) {
9972     shCount -= 24;
9973     if(shCount)
9974       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9975     else
9976       movLeft2Result(left, MSB32, result, LSB);
9977
9978     pic16_addSign(result, MSB16, sign);
9979   }
9980   else if(shCount >= 16){
9981     shCount -= 16;
9982     if(shCount)
9983       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9984     else{
9985       movLeft2Result(left, MSB24, result, LSB);
9986       movLeft2Result(left, MSB32, result, MSB16);
9987     }
9988     pic16_addSign(result, MSB24, sign);
9989   }
9990   else if(shCount >= 8){
9991     shCount -= 8;
9992     if(shCount == 1)
9993       shiftRLong(left, MSB16, result, sign);
9994     else if(shCount == 0){
9995       movLeft2Result(left, MSB16, result, LSB);
9996       movLeft2Result(left, MSB24, result, MSB16);
9997       movLeft2Result(left, MSB32, result, MSB24);
9998       pic16_addSign(result, MSB32, sign);
9999     }
10000     else{ //shcount >= 2
10001       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10002       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10003       /* the last shift is signed */
10004       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10005       pic16_addSign(result, MSB32, sign);
10006     }
10007   }
10008   else{   /* 1 <= shCount <= 7 */
10009     if(shCount <= 2){
10010       shiftRLong(left, LSB, result, sign);
10011       if(shCount == 2)
10012         shiftRLong(result, LSB, result, sign);
10013     }
10014     else{
10015       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10016       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10017       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10018     }
10019   }
10020 }
10021
10022 /*-----------------------------------------------------------------*/
10023 /* genRightShiftLiteral - right shifting by known count            */
10024 /*-----------------------------------------------------------------*/
10025 static void genRightShiftLiteral (operand *left,
10026                                   operand *right,
10027                                   operand *result,
10028                                   iCode *ic,
10029                                   int sign)
10030 {    
10031   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10032   int lsize,res_size;
10033
10034   pic16_freeAsmop(right,NULL,ic,TRUE);
10035
10036   pic16_aopOp(left,ic,FALSE);
10037   pic16_aopOp(result,ic,TRUE);
10038
10039   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10040
10041 #if VIEW_SIZE
10042   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10043                  AOP_SIZE(left));
10044 #endif
10045
10046   lsize = pic16_getDataSize(left);
10047   res_size = pic16_getDataSize(result);
10048   /* test the LEFT size !!! */
10049
10050   /* I suppose that the left size >= result size */
10051   if(shCount == 0){
10052     assert (res_size <= lsize);
10053     while (res_size--) {
10054       pic16_mov2f (AOP(result), AOP(left), res_size);
10055     } // for
10056   }
10057
10058   else if(shCount >= (lsize * 8)){
10059
10060     if(res_size == 1) {
10061       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10062       if(sign) {
10063         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10064         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10065       }
10066     } else {
10067
10068       if(sign) {
10069         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10070         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10071         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10072         while(res_size--)
10073           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10074
10075       } else {
10076
10077         while(res_size--)
10078           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10079       }
10080     }
10081   } else {
10082
10083     switch (res_size) {
10084     case 1:
10085       genrshOne (result,left,shCount,sign);
10086       break;
10087
10088     case 2:
10089       genrshTwo (result,left,shCount,sign);
10090       break;
10091
10092     case 4:
10093       genrshFour (result,left,shCount,sign);
10094       break;
10095     default :
10096       break;
10097     }
10098
10099   }
10100
10101   pic16_freeAsmop(left,NULL,ic,TRUE);
10102   pic16_freeAsmop(result,NULL,ic,TRUE);
10103 }
10104
10105 #if !(USE_GENERIC_SIGNED_SHIFT)
10106 /*-----------------------------------------------------------------*/
10107 /* genSignedRightShift - right shift of signed number              */
10108 /*-----------------------------------------------------------------*/
10109 static void genSignedRightShift (iCode *ic)
10110 {
10111   operand *right, *left, *result;
10112   int size, offset;
10113   //  char *l;
10114   symbol *tlbl, *tlbl1 ;
10115   pCodeOp *pctemp;
10116
10117   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10118
10119   /* we do it the hard way put the shift count in b
10120      and loop thru preserving the sign */
10121   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10122
10123   right = IC_RIGHT(ic);
10124   left  = IC_LEFT(ic);
10125   result = IC_RESULT(ic);
10126
10127   pic16_aopOp(right,ic,FALSE);  
10128   pic16_aopOp(left,ic,FALSE);
10129   pic16_aopOp(result,ic,FALSE);
10130
10131
10132   if ( AOP_TYPE(right) == AOP_LIT) {
10133     genRightShiftLiteral (left,right,result,ic,1);
10134     return ;
10135   }
10136   /* shift count is unknown then we have to form 
10137      a loop get the loop count in B : Note: we take
10138      only the lower order byte since shifting
10139      more that 32 bits make no sense anyway, ( the
10140      largest size of an object can be only 32 bits ) */  
10141
10142   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10143   //pic16_emitcode("inc","b");
10144   //pic16_freeAsmop (right,NULL,ic,TRUE);
10145   //pic16_aopOp(left,ic,FALSE);
10146   //pic16_aopOp(result,ic,FALSE);
10147
10148   /* now move the left to the result if they are not the
10149      same */
10150   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10151       AOP_SIZE(result) > 1) {
10152
10153     size = AOP_SIZE(result);
10154     offset=0;
10155     while (size--) { 
10156       /*
10157         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10158         if (*l == '@' && IS_AOP_PREG(result)) {
10159
10160         pic16_emitcode("mov","a,%s",l);
10161         pic16_aopPut(AOP(result),"a",offset);
10162         } else
10163         pic16_aopPut(AOP(result),l,offset);
10164       */
10165       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10166       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10167
10168       offset++;
10169     }
10170   }
10171
10172   /* mov the highest order bit to OVR */    
10173   tlbl = newiTempLabel(NULL);
10174   tlbl1= newiTempLabel(NULL);
10175
10176   size = AOP_SIZE(result);
10177   offset = size - 1;
10178
10179   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10180
10181   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10182
10183   /* offset should be 0, 1 or 3 */
10184   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10185   emitSKPNZ;
10186   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10187
10188   pic16_emitpcode(POC_MOVWF, pctemp);
10189
10190
10191   pic16_emitpLabel(tlbl->key);
10192
10193   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10194   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10195
10196   while(--size) {
10197     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10198   }
10199
10200   pic16_emitpcode(POC_DECFSZ,  pctemp);
10201   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10202   pic16_emitpLabel(tlbl1->key);
10203
10204   pic16_popReleaseTempReg(pctemp,1);
10205 #if 0
10206   size = AOP_SIZE(result);
10207   offset = size - 1;
10208   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10209   pic16_emitcode("rlc","a");
10210   pic16_emitcode("mov","ov,c");
10211   /* if it is only one byte then */
10212   if (size == 1) {
10213     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10214     MOVA(l);
10215     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10216     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10217     pic16_emitcode("mov","c,ov");
10218     pic16_emitcode("rrc","a");
10219     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10220     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10221     pic16_aopPut(AOP(result),"a",0);
10222     goto release ;
10223   }
10224
10225   reAdjustPreg(AOP(result));
10226   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10227   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10228   pic16_emitcode("mov","c,ov");
10229   while (size--) {
10230     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10231     MOVA(l);
10232     pic16_emitcode("rrc","a");         
10233     pic16_aopPut(AOP(result),"a",offset--);
10234   }
10235   reAdjustPreg(AOP(result));
10236   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10237   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10238
10239  release:
10240 #endif
10241
10242   pic16_freeAsmop(left,NULL,ic,TRUE);
10243   pic16_freeAsmop(result,NULL,ic,TRUE);
10244   pic16_freeAsmop(right,NULL,ic,TRUE);
10245 }
10246 #endif
10247
10248 #if !(USE_GENERIC_SIGNED_SHIFT)
10249 #warning This implementation of genRightShift() is incomplete!
10250 /*-----------------------------------------------------------------*/
10251 /* genRightShift - generate code for right shifting                */
10252 /*-----------------------------------------------------------------*/
10253 static void genRightShift (iCode *ic)
10254 {
10255     operand *right, *left, *result;
10256     sym_link *letype ;
10257     int size, offset;
10258     char *l;
10259     symbol *tlbl, *tlbl1 ;
10260
10261     /* if signed then we do it the hard way preserve the
10262     sign bit moving it inwards */
10263     letype = getSpec(operandType(IC_LEFT(ic)));
10264     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10265
10266     if (!SPEC_USIGN(letype)) {
10267         genSignedRightShift (ic);
10268         return ;
10269     }
10270
10271     /* signed & unsigned types are treated the same : i.e. the
10272     signed is NOT propagated inwards : quoting from the
10273     ANSI - standard : "for E1 >> E2, is equivalent to division
10274     by 2**E2 if unsigned or if it has a non-negative value,
10275     otherwise the result is implementation defined ", MY definition
10276     is that the sign does not get propagated */
10277
10278     right = IC_RIGHT(ic);
10279     left  = IC_LEFT(ic);
10280     result = IC_RESULT(ic);
10281
10282     pic16_aopOp(right,ic,FALSE);
10283
10284     /* if the shift count is known then do it 
10285     as efficiently as possible */
10286     if (AOP_TYPE(right) == AOP_LIT) {
10287         genRightShiftLiteral (left,right,result,ic, 0);
10288         return ;
10289     }
10290
10291     /* shift count is unknown then we have to form 
10292     a loop get the loop count in B : Note: we take
10293     only the lower order byte since shifting
10294     more that 32 bits make no sense anyway, ( the
10295     largest size of an object can be only 32 bits ) */  
10296
10297     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10298     pic16_emitcode("inc","b");
10299     pic16_aopOp(left,ic,FALSE);
10300     pic16_aopOp(result,ic,FALSE);
10301
10302     /* now move the left to the result if they are not the
10303     same */
10304     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10305         AOP_SIZE(result) > 1) {
10306
10307         size = AOP_SIZE(result);
10308         offset=0;
10309         while (size--) {
10310             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10311             if (*l == '@' && IS_AOP_PREG(result)) {
10312
10313                 pic16_emitcode("mov","a,%s",l);
10314                 pic16_aopPut(AOP(result),"a",offset);
10315             } else
10316                 pic16_aopPut(AOP(result),l,offset);
10317             offset++;
10318         }
10319     }
10320
10321     tlbl = newiTempLabel(NULL);
10322     tlbl1= newiTempLabel(NULL);
10323     size = AOP_SIZE(result);
10324     offset = size - 1;
10325
10326     /* if it is only one byte then */
10327     if (size == 1) {
10328
10329       tlbl = newiTempLabel(NULL);
10330       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10331         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10332         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10333       }
10334
10335       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10336       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10337       pic16_emitpLabel(tlbl->key);
10338       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10339       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10340       emitSKPC;
10341       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10342
10343       goto release ;
10344     }
10345
10346     reAdjustPreg(AOP(result));
10347     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10348     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10349     CLRC;
10350     while (size--) {
10351         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10352         MOVA(l);
10353         pic16_emitcode("rrc","a");         
10354         pic16_aopPut(AOP(result),"a",offset--);
10355     }
10356     reAdjustPreg(AOP(result));
10357
10358     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10359     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10360
10361 release:
10362     pic16_freeAsmop(left,NULL,ic,TRUE);
10363     pic16_freeAsmop (right,NULL,ic,TRUE);
10364     pic16_freeAsmop(result,NULL,ic,TRUE);
10365 }
10366 #endif
10367
10368 #if (USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genGenericShift - generates code for left or right shifting     */
10371 /*-----------------------------------------------------------------*/
10372 static void genGenericShift (iCode *ic, int isShiftLeft) {
10373   operand *left,*right, *result;
10374   int offset;
10375   int sign, signedCount;
10376   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10377   PIC_OPCODE pos_shift, neg_shift;
10378
10379   FENTRY;
10380
10381   right = IC_RIGHT(ic);
10382   left  = IC_LEFT(ic);
10383   result = IC_RESULT(ic);
10384
10385   pic16_aopOp(right,ic,FALSE);
10386   pic16_aopOp(left,ic,FALSE);
10387   pic16_aopOp(result,ic,TRUE);
10388
10389   sign = !SPEC_USIGN(operandType (left));
10390   signedCount = !SPEC_USIGN(operandType (right));
10391
10392   /* if the shift count is known then do it 
10393      as efficiently as possible */
10394   if (AOP_TYPE(right) == AOP_LIT) {
10395     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10396     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10397     // we should modify right->aopu.aop_lit here!
10398     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10399     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10400     if (isShiftLeft)
10401       pic16_genLeftShiftLiteral (left,right,result,ic);
10402     else
10403       genRightShiftLiteral (left,right,result,ic, sign);
10404
10405     goto release;
10406   } // if (right is literal)
10407
10408   /* shift count is unknown then we have to form a loop.
10409    * Note: we take only the lower order byte since shifting
10410    * more than 32 bits make no sense anyway, ( the
10411    * largest size of an object can be only 32 bits )
10412    * Note: we perform arithmetic shifts if the left operand is
10413    * signed and we do an (effective) right shift, i. e. we
10414    * shift in the sign bit from the left. */
10415    
10416   label_complete = newiTempLabel ( NULL );
10417   label_loop_pos = newiTempLabel ( NULL );
10418   label_loop_neg = NULL;
10419   label_negative = NULL;
10420   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10421   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10422
10423   if (signedCount) {
10424     // additional labels needed
10425     label_loop_neg = newiTempLabel ( NULL );
10426     label_negative = newiTempLabel ( NULL );
10427   } // if
10428
10429   // copy source to result -- this will effectively truncate the left operand to the size of result!
10430   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10431   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10432   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10433     pic16_mov2f (AOP(result),AOP(left), offset);
10434   } // for
10435
10436   // if result is longer than left, fill with zeros (or sign)
10437   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10438     if (sign && AOP_SIZE(left) > 0) {
10439       // shift signed operand -- fill with sign
10440       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10441       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10442       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10443       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10445       } // for
10446     } else {
10447       // shift unsigned operand -- fill result with zeros
10448       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10449         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10450       } // for
10451     }
10452   } // if (size mismatch)
10453
10454   pic16_mov2w (AOP(right), 0);
10455   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10456   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10457   
10458 #if 0
10459   // perform a shift by one (shift count is positive)
10460   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10461   // 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])
10462   pic16_emitpLabel (label_loop_pos->key);
10463   emitCLRC;
10464   if (sign && (pos_shift == POC_RRCF)) {
10465     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10466     emitSETC;
10467   } // if
10468   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10469   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10470   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10471 #else
10472   // perform a shift by one (shift count is positive)
10473   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10474   // 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])
10475   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10476   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10477   emitCLRC;
10478   pic16_emitpLabel (label_loop_pos->key);
10479   if (sign && (pos_shift == POC_RRCF)) {
10480     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10481     emitSETC;
10482   } // if
10483   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10484   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10485   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10486   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10487 #endif
10488
10489   if (signedCount) {
10490     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10491
10492     pic16_emitpLabel (label_negative->key);
10493     // perform a shift by -1 (shift count is negative)
10494     // 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)
10495     emitCLRC;
10496     pic16_emitpLabel (label_loop_neg->key);
10497     if (sign && (neg_shift == POC_RRCF)) {
10498       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10499       emitSETC;
10500     } // if
10501     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10502     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10503     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10504     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10505   } // if (signedCount)
10506
10507   pic16_emitpLabel (label_complete->key);
10508
10509 release:
10510   pic16_freeAsmop (right,NULL,ic,TRUE);
10511   pic16_freeAsmop(left,NULL,ic,TRUE);
10512   pic16_freeAsmop(result,NULL,ic,TRUE);
10513 }
10514
10515 static void genLeftShift (iCode *ic) {
10516   genGenericShift (ic, 1);
10517 }
10518
10519 static void genRightShift (iCode *ic) {
10520   genGenericShift (ic, 0);
10521 }
10522 #endif
10523
10524
10525 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10526 void pic16_loadFSR0(operand *op, int lit)
10527 {
10528   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10529     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10530   } else {
10531     assert (!OP_SYMBOL(op)->remat);
10532     // set up FSR0 with address of result
10533     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10534     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10535   }
10536 }
10537
10538 /*----------------------------------------------------------------*/
10539 /* pic16_derefPtr - move one byte from the location ptr points to */
10540 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10541 /*                  to the location ptr points to (doWrite != 0)   */
10542 /*----------------------------------------------------------------*/
10543 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10544 {
10545   switch (p_type) {
10546     case FPOINTER:
10547     case POINTER:
10548       if (!fsr0_setup || !*fsr0_setup)
10549       {
10550         pic16_loadFSR0( ptr, 0 );
10551         if (fsr0_setup) *fsr0_setup = 1;
10552       }
10553       if (doWrite)
10554         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10555       else
10556         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10557       break;
10558
10559     case GPOINTER:
10560       if (AOP(ptr)->aopu.aop_reg[2]) {
10561         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10562         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10563         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10564         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10565         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10566         pic16_callGenericPointerRW(doWrite, 1);
10567       } else {
10568         // data pointer (just 2 byte given)
10569         if (!fsr0_setup || !*fsr0_setup)
10570         {
10571           pic16_loadFSR0( ptr, 0 );
10572           if (fsr0_setup) *fsr0_setup = 1;
10573         }
10574         if (doWrite)
10575           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10576         else
10577           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10578       }
10579       break;
10580
10581     default:
10582       assert (0 && "invalid pointer type specified");
10583       break;
10584   }
10585 }
10586
10587 /*-----------------------------------------------------------------*/
10588 /* genUnpackBits - generates code for unpacking bits               */
10589 /*-----------------------------------------------------------------*/
10590 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10591 {    
10592   int shCnt ;
10593   sym_link *etype, *letype;
10594   int blen=0, bstr=0;
10595   int lbstr;
10596
10597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10598     etype = getSpec(operandType(result));
10599     letype = getSpec(operandType(left));
10600     
10601 //    if(IS_BITFIELD(etype)) {
10602       blen = SPEC_BLEN(etype);
10603       bstr = SPEC_BSTR(etype);
10604 //    }
10605
10606     lbstr = SPEC_BSTR( letype );
10607
10608 #if 1
10609     if((blen == 1) && (bstr < 8)) {
10610       /* it is a single bit, so use the appropriate bit instructions */
10611       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10612
10613       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10614       
10615       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10616       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10617         /* workaround to reduce the extra lfsr instruction */
10618         pic16_emitpcode(POC_BTFSC,
10619               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10620       } else {
10621         pic16_loadFSR0 (left, 0);
10622         pic16_emitpcode(POC_BTFSC,
10623               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10624       }
10625         
10626       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10627
10628       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10629       return;
10630     }
10631
10632 #endif
10633
10634         /* the following call to pic16_loadFSR0 is temporary until
10635          * optimization to handle single bit assignments is added
10636          * to the function. Until then use the old safe way! -- VR */
10637
10638     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10639         // access symbol directly
10640         pic16_mov2w (AOP(left), 0);
10641     } else {
10642       pic16_derefPtr (left, ptype, 0, NULL);
10643     }
10644
10645         /* if we have bitdisplacement then it fits   */
10646         /* into this byte completely or if length is */
10647         /* less than a byte                          */
10648         if ((shCnt = SPEC_BSTR(etype)) || 
10649                 (SPEC_BLEN(etype) <= 8))  {
10650
10651                 /* shift right acc */
10652                 AccRsh(shCnt, 0);
10653
10654                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10655                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10656
10657 /* VR -- normally I would use the following, but since we use the hack,
10658  * to avoid the masking from AccRsh, why not mask it right now? */
10659
10660 /*
10661                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10662 */
10663
10664                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10665           return ;
10666         }
10667
10668
10669
10670         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10671         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10672         exit(-1);
10673
10674     return ;
10675 }
10676
10677
10678 static void genDataPointerGet(operand *left,
10679                               operand *result,
10680                               iCode *ic)
10681 {
10682   int size, offset = 0, leoffset=0 ;
10683
10684         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10685         pic16_aopOp(result, ic, TRUE);
10686
10687         FENTRY;
10688
10689         size = AOP_SIZE(result);
10690 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10691
10692
10693 #if 0
10694         /* The following tests may save a redudant movff instruction when
10695          * accessing unions */
10696          
10697         /* if they are the same */
10698         if (operandsEqu (left, result)) {
10699                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10700                 goto release;
10701         }
10702 #endif
10703
10704 #if 0
10705         /* if they are the same registers */
10706         if (pic16_sameRegs(AOP(left),AOP(result))) {
10707                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10708                 goto release;
10709         }
10710 #endif
10711
10712 #if 1
10713         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10714                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10715                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10716                 goto release;
10717         }
10718 #endif
10719
10720
10721 #if 0
10722         if ( AOP_TYPE(left) == AOP_PCODE) {
10723                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10724                                 AOP(left)->aopu.pcop->name,
10725                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10726                                 PCOR(AOP(left)->aopu.pcop)->instance:
10727                                 PCOI(AOP(left)->aopu.pcop)->offset);
10728         }
10729 #endif
10730
10731         if(AOP(left)->aopu.pcop->type == PO_DIR)
10732                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10733
10734         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10735
10736         while (size--) {
10737                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10738                 
10739 //              pic16_DumpOp("(result)",result);
10740                 if(is_LitAOp(AOP(result))) {
10741                         pic16_mov2w(AOP(left), offset); // patch 8
10742                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10743                 } else {
10744                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10745                                 pic16_popGet(AOP(left), offset), //patch 8
10746                                 pic16_popGet(AOP(result), offset)));
10747                 }
10748
10749                 offset++;
10750                 leoffset++;
10751         }
10752
10753 release:
10754     pic16_freeAsmop(result,NULL,ic,TRUE);
10755 }
10756
10757
10758
10759 /*-----------------------------------------------------------------*/
10760 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10761 /*-----------------------------------------------------------------*/
10762 static void genNearPointerGet (operand *left, 
10763                                operand *result, 
10764                                iCode *ic)
10765 {
10766 //  asmop *aop = NULL;
10767   //regs *preg = NULL ;
10768   sym_link *rtype, *retype;
10769   sym_link *ltype, *letype;
10770
10771     FENTRY;
10772     
10773     rtype = operandType(result);
10774     retype= getSpec(rtype);
10775     ltype = operandType(left);
10776     letype= getSpec(ltype);
10777     
10778     pic16_aopOp(left,ic,FALSE);
10779
10780 //    pic16_DumpOp("(left)",left);
10781 //    pic16_DumpOp("(result)",result);
10782
10783     /* if left is rematerialisable and
10784      * result is not bit variable type and
10785      * the left is pointer to data space i.e
10786      * lower 128 bytes of space */
10787     
10788     if (AOP_TYPE(left) == AOP_PCODE
10789       && !IS_BITFIELD(retype)
10790       && DCL_TYPE(ltype) == POINTER) {
10791
10792         genDataPointerGet (left,result,ic);
10793         pic16_freeAsmop(left, NULL, ic, TRUE);
10794         return ;
10795     }
10796     
10797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10798     pic16_aopOp (result,ic,TRUE);
10799     
10800     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10801
10802 #if 1
10803     if(IS_BITFIELD( retype )
10804       && (SPEC_BLEN(operandType(result))==1)
10805     ) {
10806       iCode *nextic;
10807       pCodeOp *jop;
10808       int bitstrt, bytestrt;
10809
10810         /* if this is bitfield of size 1, see if we are checking the value
10811          * of a single bit in an if-statement,
10812          * if yes, then don't generate usual code, but execute the
10813          * genIfx directly -- VR */
10814
10815         nextic = ic->next;
10816
10817         /* CHECK: if next iCode is IFX
10818          * and current result operand is nextic's conditional operand
10819          * and current result operand live ranges ends at nextic's key number
10820          */
10821         if((nextic->op == IFX)
10822           && (result == IC_COND(nextic))
10823           && (OP_LIVETO(result) == nextic->seq)
10824           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10825           ) {
10826             /* everything is ok then */
10827             /* find a way to optimize the genIfx iCode */
10828
10829             bytestrt = SPEC_BSTR(operandType(result))/8;
10830             bitstrt = SPEC_BSTR(operandType(result))%8;
10831             
10832             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10833
10834             genIfxpCOpJump(nextic, jop);
10835             
10836             pic16_freeAsmop(left, NULL, ic, TRUE);
10837             pic16_freeAsmop(result, NULL, ic, TRUE);
10838             return;
10839         }
10840     }
10841 #endif
10842
10843     /* if bitfield then unpack the bits */
10844     if (IS_BITFIELD(letype)) 
10845       genUnpackBits (result, left, NULL, POINTER);
10846     else {
10847       /* we have can just get the values */
10848       int size = AOP_SIZE(result);
10849       int offset = 0;   
10850         
10851       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10852
10853       pic16_loadFSR0( left, 0 );
10854
10855       while(size--) {
10856         if(size) {
10857           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10858                 pic16_popGet(AOP(result), offset++)));
10859         } else {
10860           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10861                 pic16_popGet(AOP(result), offset++)));
10862         }
10863       }
10864     }
10865
10866 #if 0
10867     /* now some housekeeping stuff */
10868     if (aop) {
10869       /* we had to allocate for this iCode */
10870       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10871       pic16_freeAsmop(NULL,aop,ic,TRUE);
10872     } else { 
10873       /* we did not allocate which means left
10874        * already in a pointer register, then
10875        * if size > 0 && this could be used again
10876        * we have to point it back to where it 
10877        * belongs */
10878       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10879       if (AOP_SIZE(result) > 1
10880         && !OP_SYMBOL(left)->remat
10881         && ( OP_SYMBOL(left)->liveTo > ic->seq
10882             || ic->depth )) {
10883 //        int size = AOP_SIZE(result) - 1;
10884 //        while (size--)
10885 //          pic16_emitcode("dec","%s",rname);
10886         }
10887     }
10888 #endif
10889
10890     /* done */
10891     pic16_freeAsmop(left,NULL,ic,TRUE);
10892     pic16_freeAsmop(result,NULL,ic,TRUE);
10893 }
10894
10895 /*-----------------------------------------------------------------*/
10896 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10897 /*-----------------------------------------------------------------*/
10898 static void genPagedPointerGet (operand *left, 
10899                                operand *result, 
10900                                iCode *ic)
10901 {
10902     asmop *aop = NULL;
10903     regs *preg = NULL ;
10904     char *rname ;
10905     sym_link *rtype, *retype;    
10906
10907     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10908
10909     rtype = operandType(result);
10910     retype= getSpec(rtype);
10911     
10912     pic16_aopOp(left,ic,FALSE);
10913
10914   /* if the value is already in a pointer register
10915        then don't need anything more */
10916     if (!AOP_INPREG(AOP(left))) {
10917         /* otherwise get a free pointer register */
10918         aop = newAsmop(0);
10919         preg = getFreePtr(ic,&aop,FALSE);
10920         pic16_emitcode("mov","%s,%s",
10921                 preg->name,
10922                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10923         rname = preg->name ;
10924     } else
10925         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10926     
10927     pic16_freeAsmop(left,NULL,ic,TRUE);
10928     pic16_aopOp (result,ic,TRUE);
10929
10930     /* if bitfield then unpack the bits */
10931     if (IS_BITFIELD(retype)) 
10932         genUnpackBits (result,left,rname,PPOINTER);
10933     else {
10934         /* we have can just get the values */
10935         int size = AOP_SIZE(result);
10936         int offset = 0 ;        
10937         
10938         while (size--) {
10939             
10940             pic16_emitcode("movx","a,@%s",rname);
10941             pic16_aopPut(AOP(result),"a",offset);
10942             
10943             offset++ ;
10944             
10945             if (size)
10946                 pic16_emitcode("inc","%s",rname);
10947         }
10948     }
10949
10950     /* now some housekeeping stuff */
10951     if (aop) {
10952         /* we had to allocate for this iCode */
10953         pic16_freeAsmop(NULL,aop,ic,TRUE);
10954     } else { 
10955         /* we did not allocate which means left
10956            already in a pointer register, then
10957            if size > 0 && this could be used again
10958            we have to point it back to where it 
10959            belongs */
10960         if (AOP_SIZE(result) > 1 &&
10961             !OP_SYMBOL(left)->remat &&
10962             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10963               ic->depth )) {
10964             int size = AOP_SIZE(result) - 1;
10965             while (size--)
10966                 pic16_emitcode("dec","%s",rname);
10967         }
10968     }
10969
10970     /* done */
10971     pic16_freeAsmop(result,NULL,ic,TRUE);
10972     
10973         
10974 }
10975
10976 /*-----------------------------------------------------------------*/
10977 /* genFarPointerGet - gget value from far space                    */
10978 /*-----------------------------------------------------------------*/
10979 static void genFarPointerGet (operand *left,
10980                               operand *result, iCode *ic)
10981 {
10982     int size, offset ;
10983     sym_link *retype = getSpec(operandType(result));
10984
10985     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10986
10987     pic16_aopOp(left,ic,FALSE);
10988
10989     /* if the operand is already in dptr 
10990     then we do nothing else we move the value to dptr */
10991     if (AOP_TYPE(left) != AOP_STR) {
10992         /* if this is remateriazable */
10993         if (AOP_TYPE(left) == AOP_IMMD)
10994             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10995         else { /* we need to get it byte by byte */
10996             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10997             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10998             if (options.model == MODEL_FLAT24)
10999             {
11000                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11001             }
11002         }
11003     }
11004     /* so dptr know contains the address */
11005     pic16_freeAsmop(left,NULL,ic,TRUE);
11006     pic16_aopOp(result,ic,TRUE);
11007
11008     /* if bit then unpack */
11009     if (IS_BITFIELD(retype)) 
11010         genUnpackBits(result,left,"dptr",FPOINTER);
11011     else {
11012         size = AOP_SIZE(result);
11013         offset = 0 ;
11014
11015         while (size--) {
11016             pic16_emitcode("movx","a,@dptr");
11017             pic16_aopPut(AOP(result),"a",offset++);
11018             if (size)
11019                 pic16_emitcode("inc","dptr");
11020         }
11021     }
11022
11023     pic16_freeAsmop(result,NULL,ic,TRUE);
11024 }
11025
11026 #if 0
11027 /*-----------------------------------------------------------------*/
11028 /* genCodePointerGet - get value from code space                  */
11029 /*-----------------------------------------------------------------*/
11030 static void genCodePointerGet (operand *left,
11031                                 operand *result, iCode *ic)
11032 {
11033     int size, offset ;
11034     sym_link *retype = getSpec(operandType(result));
11035
11036     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11037
11038     pic16_aopOp(left,ic,FALSE);
11039
11040     /* if the operand is already in dptr 
11041     then we do nothing else we move the value to dptr */
11042     if (AOP_TYPE(left) != AOP_STR) {
11043         /* if this is remateriazable */
11044         if (AOP_TYPE(left) == AOP_IMMD)
11045             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11046         else { /* we need to get it byte by byte */
11047             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11048             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11049             if (options.model == MODEL_FLAT24)
11050             {
11051                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11052             }
11053         }
11054     }
11055     /* so dptr know contains the address */
11056     pic16_freeAsmop(left,NULL,ic,TRUE);
11057     pic16_aopOp(result,ic,FALSE);
11058
11059     /* if bit then unpack */
11060     if (IS_BITFIELD(retype)) 
11061         genUnpackBits(result,left,"dptr",CPOINTER);
11062     else {
11063         size = AOP_SIZE(result);
11064         offset = 0 ;
11065
11066         while (size--) {
11067             pic16_emitcode("clr","a");
11068             pic16_emitcode("movc","a,@a+dptr");
11069             pic16_aopPut(AOP(result),"a",offset++);
11070             if (size)
11071                 pic16_emitcode("inc","dptr");
11072         }
11073     }
11074
11075     pic16_freeAsmop(result,NULL,ic,TRUE);
11076 }
11077 #endif
11078
11079 #if 0
11080 /*-----------------------------------------------------------------*/
11081 /* genGenPointerGet - gget value from generic pointer space        */
11082 /*-----------------------------------------------------------------*/
11083 static void genGenPointerGet (operand *left,
11084                               operand *result, iCode *ic)
11085 {
11086   int size, offset, lit;
11087   sym_link *retype = getSpec(operandType(result));
11088
11089         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11090         pic16_aopOp(left,ic,FALSE);
11091         pic16_aopOp(result,ic,FALSE);
11092         size = AOP_SIZE(result);
11093
11094         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11095
11096         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11097
11098                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11099                 // load FSR0 from immediate
11100                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11101
11102 //              pic16_loadFSR0( left );
11103
11104                 offset = 0;
11105                 while(size--) {
11106                         if(size) {
11107                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11108                         } else {
11109                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11110                         }
11111                         offset++;
11112                 }
11113                 goto release;
11114
11115         }
11116         else { /* we need to get it byte by byte */
11117                 // set up FSR0 with address from left
11118                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11119                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11120                 
11121                 offset = 0 ;
11122
11123                 while(size--) {
11124                         if(size) {
11125                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11126                         } else {
11127                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11128                         }
11129                         offset++;
11130                 }
11131                 goto release;
11132         }
11133
11134   /* if bit then unpack */
11135         if (IS_BITFIELD(retype)) 
11136                 genUnpackBits(result,left,"BAD",GPOINTER);
11137
11138         release:
11139         pic16_freeAsmop(left,NULL,ic,TRUE);
11140         pic16_freeAsmop(result,NULL,ic,TRUE);
11141
11142 }
11143 #endif
11144
11145
11146 /*-----------------------------------------------------------------*/
11147 /* genGenPointerGet - gget value from generic pointer space        */
11148 /*-----------------------------------------------------------------*/
11149 static void genGenPointerGet (operand *left,
11150                               operand *result, iCode *ic)
11151 {
11152   int size, offset, lit;
11153   sym_link *letype = getSpec(operandType(left));
11154
11155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11156     pic16_aopOp(left,ic,FALSE);
11157     pic16_aopOp(result,ic,TRUE);
11158     size = AOP_SIZE(result);
11159
11160     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11161   
11162     /* if bit then unpack */
11163     if (IS_BITFIELD(letype)) {
11164       genUnpackBits(result,left,"BAD",GPOINTER);
11165       goto release;
11166     }
11167
11168     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11169
11170       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11171       // load FSR0 from immediate
11172       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11173
11174       werror(W_POSSBUG2, __FILE__, __LINE__);
11175
11176       offset = 0;
11177       while(size--) {
11178         if(size) {
11179           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11180         } else {
11181           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11182         }
11183         offset++;
11184       }
11185
11186       goto release;
11187
11188     } else { /* we need to get it byte by byte */
11189
11190       /* set up WREG:PRODL:FSR0L with address from left */
11191       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11192       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11193       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11194       
11195       pic16_callGenericPointerRW(0, size);
11196       
11197       assignResultValue(result, 1);
11198       
11199       goto release;
11200     }
11201
11202 release:
11203   pic16_freeAsmop(left,NULL,ic,TRUE);
11204   pic16_freeAsmop(result,NULL,ic,TRUE);
11205 }
11206
11207 /*-----------------------------------------------------------------*/
11208 /* genConstPointerGet - get value from const generic pointer space */
11209 /*-----------------------------------------------------------------*/
11210 static void genConstPointerGet (operand *left,
11211                                 operand *result, iCode *ic)
11212 {
11213   //sym_link *retype = getSpec(operandType(result));
11214   // symbol *albl = newiTempLabel(NULL);        // patch 15
11215   // symbol *blbl = newiTempLabel(NULL);        //
11216   // PIC_OPCODE poc;                            // patch 15
11217   int size;
11218   int offset = 0;
11219
11220   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11221   pic16_aopOp(left,ic,FALSE);
11222   pic16_aopOp(result,ic,TRUE);
11223   size = AOP_SIZE(result);
11224
11225   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11226
11227   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11228
11229   // set up table pointer
11230   if( (AOP_TYPE(left) == AOP_PCODE) 
11231       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11232           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11233     {
11234       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11235       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11236       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11237       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11238       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11239       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11240   } else {
11241     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11242     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11243     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11244   }
11245
11246   while(size--) {
11247     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11248     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11249     offset++;
11250   }
11251     
11252   pic16_freeAsmop(left,NULL,ic,TRUE);
11253   pic16_freeAsmop(result,NULL,ic,TRUE);
11254 }
11255
11256
11257 /*-----------------------------------------------------------------*/
11258 /* genPointerGet - generate code for pointer get                   */
11259 /*-----------------------------------------------------------------*/
11260 static void genPointerGet (iCode *ic)
11261 {
11262   operand *left, *result ;
11263   sym_link *type, *etype;
11264   int p_type;
11265
11266     FENTRY;
11267     
11268     left = IC_LEFT(ic);
11269     result = IC_RESULT(ic) ;
11270
11271     /* depending on the type of pointer we need to
11272     move it to the correct pointer register */
11273     type = operandType(left);
11274     etype = getSpec(type);
11275
11276 #if 0
11277     if (IS_PTR_CONST(type))
11278 #else
11279     if (IS_CODEPTR(type))
11280 #endif
11281       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11282
11283     /* if left is of type of pointer then it is simple */
11284     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11285       p_type = DCL_TYPE(type);
11286     else {
11287       /* we have to go by the storage class */
11288       p_type = PTR_TYPE(SPEC_OCLS(etype));
11289
11290       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11291
11292       if (SPEC_OCLS(etype)->codesp ) {
11293         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11294         //p_type = CPOINTER ;   
11295       } else
11296       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11297         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11298         /*p_type = FPOINTER ;*/ 
11299       } else
11300       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11301         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11302         /* p_type = PPOINTER; */
11303       } else
11304       if (SPEC_OCLS(etype) == idata ) {
11305         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11306         /* p_type = IPOINTER; */
11307       } else {
11308         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11309         /* p_type = POINTER ; */
11310       }
11311     }
11312
11313     /* now that we have the pointer type we assign
11314     the pointer values */
11315     switch (p_type) {
11316       case POINTER:     
11317       case IPOINTER:
11318         genNearPointerGet (left,result,ic);
11319         break;
11320
11321       case PPOINTER:
11322         genPagedPointerGet(left,result,ic);
11323         break;
11324
11325       case FPOINTER:
11326         genFarPointerGet (left,result,ic);
11327         break;
11328
11329       case CPOINTER:
11330         genConstPointerGet (left,result,ic);
11331         //pic16_emitcodePointerGet (left,result,ic);
11332         break;
11333
11334       case GPOINTER:
11335 #if 0
11336       if (IS_PTR_CONST(type))
11337         genConstPointerGet (left,result,ic);
11338       else
11339 #endif
11340         genGenPointerGet (left,result,ic);
11341       break;
11342
11343     default:
11344       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11345               "genPointerGet: illegal pointer type");
11346     
11347     }
11348 }
11349
11350 /*-----------------------------------------------------------------*/
11351 /* genPackBits - generates code for packed bit storage             */
11352 /*-----------------------------------------------------------------*/
11353 static void genPackBits (sym_link    *etype , operand *result,
11354                          operand *right ,
11355                          char *rname, int p_type)
11356 {
11357   int shCnt = 0 ;
11358   int offset = 0  ;
11359   int rLen = 0 ;
11360   int blen, bstr ;   
11361   sym_link *retype;
11362
11363         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11364         blen = SPEC_BLEN(etype);
11365         bstr = SPEC_BSTR(etype);
11366
11367         retype = getSpec(operandType(right));
11368
11369         if(AOP_TYPE(right) == AOP_LIT) {
11370                 if((blen == 1) && (bstr < 8)) {
11371                   unsigned long lit;
11372                         /* it is a single bit, so use the appropriate bit instructions */
11373
11374                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11375
11376                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11377 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11378                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11379                                 /* workaround to reduce the extra lfsr instruction */
11380                                 if(lit) {
11381                                         pic16_emitpcode(POC_BSF,
11382                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11383                                 } else {
11384                                         pic16_emitpcode(POC_BCF,
11385                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11386                                 }
11387                         } else {
11388                                 pic16_loadFSR0(result, 0);
11389                                 if(lit) {
11390                                         pic16_emitpcode(POC_BSF,
11391                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11392                                 } else {
11393                                         pic16_emitpcode(POC_BCF,
11394                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11395                                 }
11396                         }
11397         
11398                   return;
11399                 }
11400                 /* move literal to W */
11401                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11402                 offset++;
11403         } else
11404         if(IS_BITFIELD(retype) 
11405           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11406           && (blen == 1)) {
11407           int rblen, rbstr;
11408
11409             rblen = SPEC_BLEN( retype );
11410             rbstr = SPEC_BSTR( retype );
11411             
11412
11413             if(IS_BITFIELD(etype)) {
11414               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11415               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11416             } else {
11417               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11418             }
11419             
11420             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11421             
11422             if(IS_BITFIELD(etype)) {
11423               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11424             } else {
11425               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11426             }
11427
11428             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11429             
11430             return;
11431         } else {
11432           /* move right to W */
11433           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11434         }
11435
11436         /* if the bit length is less than or   */
11437         /* it exactly fits a byte then         */
11438         if((shCnt=SPEC_BSTR(etype))
11439                 || SPEC_BLEN(etype) <= 8 )  {
11440                 int fsr0_setup = 0;
11441
11442                 if (blen != 8 || bstr != 0) {
11443                   // we need to combine the value with the old value
11444                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11445
11446           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11447                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11448                 
11449                   /* shift left acc */
11450                   AccLsh(shCnt);
11451
11452                   /* using PRODH as a temporary register here */
11453                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11454
11455                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11456                     /* access symbol directly */
11457                     pic16_mov2w (AOP(result), 0);
11458                   } else {
11459                     /* get old value */
11460                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11461                   }
11462 #if 1
11463                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11464                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11465                                         (unsigned char)(0xff >> (8-bstr))) ));
11466                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11467                 } // if (blen != 8 || bstr != 0)
11468
11469                 /* write new value back */
11470                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11471                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11472                 } else {
11473                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11474                }
11475 #endif
11476
11477           return;
11478         }
11479
11480
11481 #if 0
11482         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11483         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11484         exit(-1);
11485 #endif
11486
11487
11488     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11489     rLen = SPEC_BLEN(etype)-8;
11490     
11491     /* now generate for lengths greater than one byte */
11492     while (1) {
11493         rLen -= 8 ;
11494         if (rLen <= 0 ) {
11495           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11496           break ;
11497         }
11498
11499         switch (p_type) {
11500             case POINTER:
11501                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11502                 break;
11503
11504 /*
11505             case FPOINTER:
11506                 MOVA(l);
11507                 pic16_emitcode("movx","@dptr,a");
11508                 break;
11509
11510             case GPOINTER:
11511                 MOVA(l);
11512                 DEBUGpic16_emitcode(";lcall","__gptrput");
11513                 break;  
11514 */
11515           default:
11516             assert(0);
11517         }   
11518
11519
11520         pic16_mov2w(AOP(right), offset++);
11521     }
11522
11523     /* last last was not complete */
11524     if (rLen)   {
11525         /* save the byte & read byte */
11526         switch (p_type) {
11527             case POINTER:
11528 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11529                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11530                 break;
11531
11532 /*
11533             case FPOINTER:
11534                 pic16_emitcode ("mov","b,a");
11535                 pic16_emitcode("movx","a,@dptr");
11536                 break;
11537
11538             case GPOINTER:
11539                 pic16_emitcode ("push","b");
11540                 pic16_emitcode ("push","acc");
11541                 pic16_emitcode ("lcall","__gptrget");
11542                 pic16_emitcode ("pop","b");
11543                 break;
11544 */
11545             default:
11546               assert(0);
11547         }
11548         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11549         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11550         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11551 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11552 //        pic16_emitcode ("orl","a,b");
11553     }
11554
11555 //    if (p_type == GPOINTER)
11556 //        pic16_emitcode("pop","b");
11557
11558     switch (p_type) {
11559
11560       case POINTER:
11561         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11562 //      pic16_emitcode("mov","@%s,a",rname);
11563         break;
11564 /*
11565       case FPOINTER:
11566         pic16_emitcode("movx","@dptr,a");
11567         break;
11568         
11569       case GPOINTER:
11570         DEBUGpic16_emitcode(";lcall","__gptrput");
11571         break;                  
11572 */
11573       default:
11574         assert(0);
11575     }
11576     
11577 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11578 }
11579 /*-----------------------------------------------------------------*/
11580 /* genDataPointerSet - remat pointer to data space                 */
11581 /*-----------------------------------------------------------------*/
11582 static void genDataPointerSet(operand *right,
11583                               operand *result,
11584                               iCode *ic)
11585 {
11586     int size, offset = 0, resoffset=0 ;
11587
11588     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11589     pic16_aopOp(right,ic,FALSE);
11590
11591     size = AOP_SIZE(right);
11592
11593 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11594
11595 #if 0
11596     if ( AOP_TYPE(result) == AOP_PCODE) {
11597       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11598               AOP(result)->aopu.pcop->name,
11599                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11600               PCOR(AOP(result)->aopu.pcop)->instance:
11601               PCOI(AOP(result)->aopu.pcop)->offset);
11602     }
11603 #endif
11604
11605         if(AOP(result)->aopu.pcop->type == PO_DIR)
11606                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11607
11608         while (size--) {
11609                 if (AOP_TYPE(right) == AOP_LIT) {
11610                   unsigned int lit;
11611
11612                     if(!IS_FLOAT(operandType( right )))
11613                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11614                     else {
11615                       union {
11616                         unsigned long lit_int;
11617                         float lit_float;
11618                       } info;
11619         
11620                         /* take care if literal is a float */
11621                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11622                         lit = info.lit_int;
11623                     }
11624
11625                     lit = lit >> (8*offset);
11626                     if(lit&0xff) {
11627                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11628                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11629                     } else {
11630                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11631                     }
11632                 } else {
11633                   pic16_mov2w(AOP(right), offset);
11634                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11635                 }
11636                 offset++;
11637                 resoffset++;
11638         }
11639
11640     pic16_freeAsmop(right,NULL,ic,TRUE);
11641 }
11642
11643
11644
11645 /*-----------------------------------------------------------------*/
11646 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11647 /*-----------------------------------------------------------------*/
11648 static void genNearPointerSet (operand *right,
11649                                operand *result, 
11650                                iCode *ic)
11651 {
11652   asmop *aop = NULL;
11653   sym_link *retype;
11654   sym_link *ptype = operandType(result);
11655   sym_link *resetype;
11656     
11657         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11658         retype= getSpec(operandType(right));
11659         resetype = getSpec(operandType(result));
11660   
11661         pic16_aopOp(result,ic,FALSE);
11662     
11663         /* if the result is rematerializable &
11664          * in data space & not a bit variable */
11665         
11666         /* and result is not a bit variable */
11667         if (AOP_TYPE(result) == AOP_PCODE
11668 //              && AOP_TYPE(result) == AOP_IMMD
11669                 && DCL_TYPE(ptype) == POINTER
11670                 && !IS_BITFIELD(retype)
11671                 && !IS_BITFIELD(resetype)) {
11672
11673                 genDataPointerSet (right,result,ic);
11674                 pic16_freeAsmop(result,NULL,ic,TRUE);
11675           return;
11676         }
11677
11678         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11679         pic16_aopOp(right,ic,FALSE);
11680         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11681
11682         /* if bitfield then unpack the bits */
11683         if (IS_BITFIELD(resetype)) {
11684                 genPackBits (resetype, result, right, NULL, POINTER);
11685         } else {
11686                 /* we have can just get the values */
11687           int size = AOP_SIZE(right);
11688           int offset = 0 ;    
11689
11690             pic16_loadFSR0(result, 0);
11691             
11692                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11693                 while (size--) {
11694                                 if (AOP_TYPE(right) == AOP_LIT) {
11695                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11696                                         if (size) {
11697                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11698                                         } else {
11699                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11700                                         }
11701                                 } else { // no literal
11702                                         if(size) {
11703                                                 pic16_emitpcode(POC_MOVFF,
11704                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11705                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11706                                         } else {
11707                                                 pic16_emitpcode(POC_MOVFF,
11708                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11709                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11710                                         }
11711                                 }
11712                         offset++;
11713                 }
11714         }
11715
11716         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11717         /* now some housekeeping stuff */
11718         if (aop) {
11719           /* we had to allocate for this iCode */
11720           pic16_freeAsmop(NULL,aop,ic,TRUE);
11721         } else { 
11722           /* we did not allocate which means left
11723            * already in a pointer register, then
11724            * if size > 0 && this could be used again
11725            * we have to point it back to where it 
11726            * belongs */
11727           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11728           if (AOP_SIZE(right) > 1
11729             && !OP_SYMBOL(result)->remat
11730             && ( OP_SYMBOL(result)->liveTo > ic->seq
11731             || ic->depth )) {
11732
11733               int size = AOP_SIZE(right) - 1;
11734
11735                 while (size--)
11736                   pic16_emitcode("decf","fsr0,f");
11737                   //pic16_emitcode("dec","%s",rname);
11738             }
11739         }
11740
11741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11742     /* done */
11743 //release:
11744     pic16_freeAsmop(right,NULL,ic,TRUE);
11745     pic16_freeAsmop(result,NULL,ic,TRUE);
11746 }
11747
11748 /*-----------------------------------------------------------------*/
11749 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11750 /*-----------------------------------------------------------------*/
11751 static void genPagedPointerSet (operand *right,
11752                                operand *result, 
11753                                iCode *ic)
11754 {
11755     asmop *aop = NULL;
11756     regs *preg = NULL ;
11757     char *rname , *l;
11758     sym_link *retype;
11759        
11760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11761
11762     retype= getSpec(operandType(right));
11763     
11764     pic16_aopOp(result,ic,FALSE);
11765     
11766     /* if the value is already in a pointer register
11767        then don't need anything more */
11768     if (!AOP_INPREG(AOP(result))) {
11769         /* otherwise get a free pointer register */
11770         aop = newAsmop(0);
11771         preg = getFreePtr(ic,&aop,FALSE);
11772         pic16_emitcode("mov","%s,%s",
11773                 preg->name,
11774                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11775         rname = preg->name ;
11776     } else
11777         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11778     
11779     pic16_freeAsmop(result,NULL,ic,TRUE);
11780     pic16_aopOp (right,ic,FALSE);
11781
11782     /* if bitfield then unpack the bits */
11783     if (IS_BITFIELD(retype)) 
11784         genPackBits (retype,result,right,rname,PPOINTER);
11785     else {
11786         /* we have can just get the values */
11787         int size = AOP_SIZE(right);
11788         int offset = 0 ;        
11789         
11790         while (size--) {
11791             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11792             
11793             MOVA(l);
11794             pic16_emitcode("movx","@%s,a",rname);
11795
11796             if (size)
11797                 pic16_emitcode("inc","%s",rname);
11798
11799             offset++;
11800         }
11801     }
11802     
11803     /* now some housekeeping stuff */
11804     if (aop) {
11805         /* we had to allocate for this iCode */
11806         pic16_freeAsmop(NULL,aop,ic,TRUE);
11807     } else { 
11808         /* we did not allocate which means left
11809            already in a pointer register, then
11810            if size > 0 && this could be used again
11811            we have to point it back to where it 
11812            belongs */
11813         if (AOP_SIZE(right) > 1 &&
11814             !OP_SYMBOL(result)->remat &&
11815             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11816               ic->depth )) {
11817             int size = AOP_SIZE(right) - 1;
11818             while (size--)
11819                 pic16_emitcode("dec","%s",rname);
11820         }
11821     }
11822
11823     /* done */
11824     pic16_freeAsmop(right,NULL,ic,TRUE);
11825     
11826         
11827 }
11828
11829 /*-----------------------------------------------------------------*/
11830 /* genFarPointerSet - set value from far space                     */
11831 /*-----------------------------------------------------------------*/
11832 static void genFarPointerSet (operand *right,
11833                               operand *result, iCode *ic)
11834 {
11835     int size, offset ;
11836     sym_link *retype = getSpec(operandType(right));
11837
11838     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11839     pic16_aopOp(result,ic,FALSE);
11840
11841     /* if the operand is already in dptr 
11842     then we do nothing else we move the value to dptr */
11843     if (AOP_TYPE(result) != AOP_STR) {
11844         /* if this is remateriazable */
11845         if (AOP_TYPE(result) == AOP_IMMD)
11846             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11847         else { /* we need to get it byte by byte */
11848             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11849             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11850             if (options.model == MODEL_FLAT24)
11851             {
11852                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11853             }
11854         }
11855     }
11856     /* so dptr know contains the address */
11857     pic16_freeAsmop(result,NULL,ic,TRUE);
11858     pic16_aopOp(right,ic,FALSE);
11859
11860     /* if bit then unpack */
11861     if (IS_BITFIELD(retype)) 
11862         genPackBits(retype,result,right,"dptr",FPOINTER);
11863     else {
11864         size = AOP_SIZE(right);
11865         offset = 0 ;
11866
11867         while (size--) {
11868             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11869             MOVA(l);
11870             pic16_emitcode("movx","@dptr,a");
11871             if (size)
11872                 pic16_emitcode("inc","dptr");
11873         }
11874     }
11875
11876     pic16_freeAsmop(right,NULL,ic,TRUE);
11877 }
11878
11879 /*-----------------------------------------------------------------*/
11880 /* genGenPointerSet - set value from generic pointer space         */
11881 /*-----------------------------------------------------------------*/
11882 #if 0
11883 static void genGenPointerSet (operand *right,
11884                               operand *result, iCode *ic)
11885 {
11886         int i, size, offset, lit;
11887         sym_link *retype = getSpec(operandType(right));
11888
11889         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11890
11891         pic16_aopOp(result,ic,FALSE);
11892         pic16_aopOp(right,ic,FALSE);
11893         size = AOP_SIZE(right);
11894         offset = 0;
11895
11896         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11897
11898         /* if the operand is already in dptr 
11899                 then we do nothing else we move the value to dptr */
11900         if (AOP_TYPE(result) != AOP_STR) {
11901                 /* if this is remateriazable */
11902                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11903                 // WARNING: anythig until "else" is untested!
11904                 if (AOP_TYPE(result) == AOP_IMMD) {
11905                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11906                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11907                         // load FSR0 from immediate
11908                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11909                         offset = 0;
11910                         while(size--) {
11911                                 if(size) {
11912                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11913                                 } else {
11914                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11915                                 }
11916                                 offset++;
11917                         }
11918                         goto release;
11919                 }
11920                 else { /* we need to get it byte by byte */
11921                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11922                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11923
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)));
11926                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11927
11928                         /* hack hack! see if this the FSR. If so don't load W */
11929                         if(AOP_TYPE(right) != AOP_ACC) {
11930
11931                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11932
11933                                 if(AOP_TYPE(right) == AOP_LIT)
11934                                 {
11935                                         // copy literal
11936                                         // note: pic16_popGet handles sign extension
11937                                         for(i=0;i<size;i++) {
11938                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11939                                                 if(i < size-1)
11940                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11941                                                 else
11942                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11943                                         }
11944                                 } else {
11945                                         // copy regs
11946
11947                                         for(i=0;i<size;i++) {
11948                                                 if(i < size-1)
11949                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11950                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11951                                                 else
11952                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11953                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11954                                         }
11955                                 }
11956                                 goto release;
11957                         } 
11958                         // right = ACC
11959                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11960                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11961                         goto release;
11962         } // if (AOP_TYPE(result) != AOP_IMMD)
11963
11964         } // if (AOP_TYPE(result) != AOP_STR)
11965         /* so dptr know contains the address */
11966
11967
11968         /* if bit then unpack */
11969         if (IS_BITFIELD(retype)) 
11970                 genPackBits(retype,result,right,"dptr",GPOINTER);
11971         else {
11972                 size = AOP_SIZE(right);
11973                 offset = 0 ;
11974
11975                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11976
11977                 // set up FSR0 with address of result
11978                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11979                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11980         
11981                 while (size--) {
11982                         if (AOP_TYPE(right) == AOP_LIT) {
11983                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11984                                 if (size) {
11985                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11986                                 } else {
11987                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11988                                 }
11989                         } else { // no literal
11990                                 if(size) {
11991                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11992                                 } else {
11993                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11994                                 }
11995                         }
11996                         offset++;
11997                 }
11998         }
11999
12000         release:
12001         pic16_freeAsmop(right,NULL,ic,TRUE);
12002         pic16_freeAsmop(result,NULL,ic,TRUE);
12003 }
12004 #endif
12005
12006 static void genGenPointerSet (operand *right,
12007                               operand *result, iCode *ic)
12008 {
12009   int size;
12010   sym_link *retype = getSpec(operandType(result));
12011
12012     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12013
12014     pic16_aopOp(result,ic,FALSE);
12015     pic16_aopOp(right,ic,FALSE);
12016     size = AOP_SIZE(right);
12017
12018     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12019
12020
12021     /* if bit then unpack */
12022     if (IS_BITFIELD(retype)) {
12023 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12024       genPackBits(retype,result,right,"dptr",GPOINTER);
12025       goto release;
12026     }
12027
12028     size = AOP_SIZE(right);
12029
12030     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12031
12032
12033     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12034
12035     /* value of right+0 is placed on stack, which will be retrieved
12036      * by the support function this restoring the stack. The important
12037      * thing is that there is no need to manually restore stack pointer
12038      * here */
12039     pushaop(AOP(right), 0);
12040 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12041     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12042     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12043     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12044     
12045     /* load address to write to in WREG:FSR0H:FSR0L */
12046     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12047                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12048     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12049                                 pic16_popCopyReg(&pic16_pc_prodl)));
12050     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12051     
12052     pic16_callGenericPointerRW(1, size);
12053
12054 release:
12055     pic16_freeAsmop(right,NULL,ic,TRUE);
12056     pic16_freeAsmop(result,NULL,ic,TRUE);
12057 }
12058
12059 /*-----------------------------------------------------------------*/
12060 /* genPointerSet - stores the value into a pointer location        */
12061 /*-----------------------------------------------------------------*/
12062 static void genPointerSet (iCode *ic)
12063 {    
12064   operand *right, *result ;
12065   sym_link *type, *etype;
12066   int p_type;
12067
12068     FENTRY;
12069
12070     right = IC_RIGHT(ic);
12071     result = IC_RESULT(ic) ;
12072
12073     /* depending on the type of pointer we need to
12074     move it to the correct pointer register */
12075     type = operandType(result);
12076     etype = getSpec(type);
12077     
12078     /* if left is of type of pointer then it is simple */
12079     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12080         p_type = DCL_TYPE(type);
12081     }
12082     else {
12083         /* we have to go by the storage class */
12084         p_type = PTR_TYPE(SPEC_OCLS(etype));
12085
12086 /*      if (SPEC_OCLS(etype)->codesp ) { */
12087 /*          p_type = CPOINTER ;  */
12088 /*      } */
12089 /*      else */
12090 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12091 /*              p_type = FPOINTER ; */
12092 /*          else */
12093 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12094 /*                  p_type = PPOINTER ; */
12095 /*              else */
12096 /*                  if (SPEC_OCLS(etype) == idata ) */
12097 /*                      p_type = IPOINTER ; */
12098 /*                  else */
12099 /*                      p_type = POINTER ; */
12100     }
12101
12102     /* now that we have the pointer type we assign
12103     the pointer values */
12104     switch (p_type) {
12105       case POINTER:
12106       case IPOINTER:
12107         genNearPointerSet (right,result,ic);
12108         break;
12109
12110       case PPOINTER:
12111         genPagedPointerSet (right,result,ic);
12112         break;
12113
12114       case FPOINTER:
12115         genFarPointerSet (right,result,ic);
12116         break;
12117         
12118       case GPOINTER:
12119         genGenPointerSet (right,result,ic);
12120         break;
12121
12122       default:
12123         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12124           "genPointerSet: illegal pointer type");
12125     }
12126 }
12127
12128 /*-----------------------------------------------------------------*/
12129 /* genIfx - generate code for Ifx statement                        */
12130 /*-----------------------------------------------------------------*/
12131 static void genIfx (iCode *ic, iCode *popIc)
12132 {
12133   operand *cond = IC_COND(ic);
12134   int isbit =0;
12135
12136     FENTRY;
12137
12138     pic16_aopOp(cond,ic,FALSE);
12139
12140     /* get the value into acc */
12141     if (AOP_TYPE(cond) != AOP_CRY)
12142       pic16_toBoolean(cond);
12143     else
12144       isbit = 1;
12145     /* the result is now in the accumulator */
12146     pic16_freeAsmop(cond,NULL,ic,TRUE);
12147
12148     /* if there was something to be popped then do it */
12149     if (popIc)
12150       genIpop(popIc);
12151
12152     /* if the condition is  a bit variable */
12153     if (isbit && IS_ITEMP(cond) && 
12154         SPIL_LOC(cond)) {
12155       genIfxJump(ic,"c");
12156       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12157     } else {
12158       if (isbit && !IS_ITEMP(cond))
12159         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12160         else
12161         genIfxJump(ic,"a");
12162     }
12163     ic->generated = 1;
12164 }
12165
12166 /*-----------------------------------------------------------------*/
12167 /* genAddrOf - generates code for address of                       */
12168 /*-----------------------------------------------------------------*/
12169 static void genAddrOf (iCode *ic)
12170 {
12171   operand *result, *left;
12172   int size;
12173   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12174   pCodeOp *pcop0, *pcop1, *pcop2;
12175
12176     FENTRY;
12177
12178     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12179
12180     sym = OP_SYMBOL( IC_LEFT(ic) );
12181     
12182     if(sym->onStack) {
12183       /* get address of symbol on stack */
12184       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12185 #if 0
12186       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12187                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12188 #endif
12189
12190       // operands on stack are accessible via "FSR2 + index" with index
12191       // starting at 2 for arguments and growing from 0 downwards for
12192       // local variables (index == 0 is not assigned so we add one here)
12193       {
12194         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12195         if (soffs <= 0) {
12196           assert (soffs < 0);
12197           soffs++;
12198         } // if
12199         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12200         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12201         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12202         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12203         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12204         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12205         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12206       }
12207
12208       goto release;
12209     }
12210         
12211 //      if(pic16_debug_verbose) {
12212 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12213 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12214 //      }
12215         
12216     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12217     size = AOP_SIZE(IC_RESULT(ic));
12218
12219     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12220     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12221     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12222         
12223     if (size == 3) {
12224       pic16_emitpcode(POC_MOVLW, pcop0);
12225       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12226       pic16_emitpcode(POC_MOVLW, pcop1);
12227       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12228       pic16_emitpcode(POC_MOVLW, pcop2);
12229       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12230     } else
12231     if (size == 2) {
12232       pic16_emitpcode(POC_MOVLW, pcop0);
12233       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12234       pic16_emitpcode(POC_MOVLW, pcop1);
12235     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12236     } else {
12237       pic16_emitpcode(POC_MOVLW, pcop0);
12238       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12239     }
12240
12241     pic16_freeAsmop(left, NULL, ic, FALSE);
12242 release:
12243     pic16_freeAsmop(result,NULL,ic,TRUE);
12244 }
12245
12246
12247 #if 0
12248 /*-----------------------------------------------------------------*/
12249 /* genFarFarAssign - assignment when both are in far space         */
12250 /*-----------------------------------------------------------------*/
12251 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12252 {
12253     int size = AOP_SIZE(right);
12254     int offset = 0;
12255     char *l ;
12256     /* first push the right side on to the stack */
12257     while (size--) {
12258         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12259         MOVA(l);
12260         pic16_emitcode ("push","acc");
12261     }
12262     
12263     pic16_freeAsmop(right,NULL,ic,FALSE);
12264     /* now assign DPTR to result */
12265     pic16_aopOp(result,ic,FALSE);
12266     size = AOP_SIZE(result);
12267     while (size--) {
12268         pic16_emitcode ("pop","acc");
12269         pic16_aopPut(AOP(result),"a",--offset);
12270     }
12271     pic16_freeAsmop(result,NULL,ic,FALSE);
12272         
12273 }
12274 #endif
12275
12276 /*-----------------------------------------------------------------*/
12277 /* genAssign - generate code for assignment                        */
12278 /*-----------------------------------------------------------------*/
12279 static void genAssign (iCode *ic)
12280 {
12281   operand *result, *right;
12282   int size, offset,know_W;
12283   unsigned long lit = 0L;
12284
12285   result = IC_RESULT(ic);
12286   right  = IC_RIGHT(ic) ;
12287
12288   FENTRY;
12289   
12290   /* if they are the same */
12291   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12292     return ;
12293
12294   /* reversed order operands are aopOp'ed so that result operand
12295    * is effective in case right is a stack symbol. This maneauver
12296    * allows to use the _G.resDirect flag later */
12297   pic16_aopOp(result,ic,TRUE);
12298   pic16_aopOp(right,ic,FALSE);
12299
12300   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12301
12302   /* if they are the same registers */
12303   if (pic16_sameRegs(AOP(right),AOP(result)))
12304     goto release;
12305
12306   /* if the result is a bit */
12307   if (AOP_TYPE(result) == AOP_CRY) {
12308     /* if the right size is a literal then
12309        we know what the value is */
12310     if (AOP_TYPE(right) == AOP_LIT) {
12311           
12312       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12313                   pic16_popGet(AOP(result),0));
12314
12315       if (((int) operandLitValue(right))) 
12316         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12317                        AOP(result)->aopu.aop_dir,
12318                        AOP(result)->aopu.aop_dir);
12319       else
12320         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12321                        AOP(result)->aopu.aop_dir,
12322                        AOP(result)->aopu.aop_dir);
12323       goto release;
12324     }
12325
12326     /* the right is also a bit variable */
12327     if (AOP_TYPE(right) == AOP_CRY) {
12328       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12329       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12330       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12331
12332       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12333                      AOP(result)->aopu.aop_dir,
12334                      AOP(result)->aopu.aop_dir);
12335       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12336                      AOP(right)->aopu.aop_dir,
12337                      AOP(right)->aopu.aop_dir);
12338       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12339                      AOP(result)->aopu.aop_dir,
12340                      AOP(result)->aopu.aop_dir);
12341       goto release ;
12342     }
12343
12344     /* we need to or */
12345     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12346     pic16_toBoolean(right);
12347     emitSKPZ;
12348     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12349     //pic16_aopPut(AOP(result),"a",0);
12350     goto release ;
12351   }
12352
12353   /* bit variables done */
12354   /* general case */
12355   size = AOP_SIZE(result);
12356   offset = 0 ;
12357
12358   if(AOP_TYPE(right) == AOP_LIT) {
12359         if(!IS_FLOAT(operandType( right )))
12360                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12361         else {
12362            union {
12363               unsigned long lit_int;
12364               float lit_float;
12365             } info;
12366         
12367                 /* take care if literal is a float */
12368                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12369                 lit = info.lit_int;
12370         }
12371   }
12372
12373 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12374 //                      sizeof(unsigned long int), sizeof(float));
12375
12376
12377   if (AOP_TYPE(right) == AOP_REG) {
12378     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12379     while (size--) {
12380       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12381     } // while
12382     goto release;
12383   }
12384
12385   /* when do we have to read the program memory?
12386    * - if right itself is a symbol in code space
12387    *   (we don't care what it points to if it's a pointer)
12388    * - AND right is not a function (we would want its address)
12389    */
12390   if(AOP_TYPE(right) != AOP_LIT
12391         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12392         && !IS_FUNC(OP_SYM_TYPE(right))
12393         && !IS_ITEMP(right))
12394   {
12395         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12396         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12397
12398         // set up table pointer
12399         if(is_LitOp(right)) {
12400 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12401                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12402                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12403                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12404                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12405                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12406                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12407         } else {
12408 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12409                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12410                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12411                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12412                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12413                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12414                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12415         }
12416
12417         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12418         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12419         while(size--) {
12420                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12421                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12422                         pic16_popGet(AOP(result),offset)));
12423                 offset++;
12424         }
12425
12426         /* FIXME: for pointers we need to extend differently (according
12427          * to pointer type DATA/CODE/EEPROM/... :*/
12428         size = getSize(OP_SYM_TYPE(right));
12429         if(AOP_SIZE(result) > size) {
12430                 size = AOP_SIZE(result) - size;
12431                 while(size--) {
12432                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12433                         offset++;
12434                 }
12435         }
12436         goto release;
12437   }
12438
12439
12440
12441 #if 0
12442 /* VR - What is this?! */
12443   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12445     if(aopIdx(AOP(result),0) == 4) {
12446
12447       /* this is a workaround to save value of right into wreg too,
12448        * value of wreg is going to be used later */
12449       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12450       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12451       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12452       goto release;
12453     } else
12454 //      assert(0);
12455       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12456   }
12457 #endif
12458
12459   know_W=-1;
12460   while (size--) {
12461   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12462     if(AOP_TYPE(right) == AOP_LIT) {
12463       if(lit&0xff) {
12464         if(know_W != (lit&0xff))
12465           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12466         know_W = lit&0xff;
12467         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12468       } else
12469         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12470
12471       lit >>= 8;
12472
12473     } else if (AOP_TYPE(right) == AOP_CRY) {
12474       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12475       if(offset == 0) {
12476         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12477         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12478         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12479       }
12480     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12481         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12482         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12483     } else {
12484       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12485
12486       if(!_G.resDirect)         /* use this aopForSym feature */
12487         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12488     }
12489             
12490     offset++;
12491   }
12492   
12493  release:
12494   pic16_freeAsmop (right,NULL,ic,FALSE);
12495   pic16_freeAsmop (result,NULL,ic,TRUE);
12496 }   
12497
12498 /*-----------------------------------------------------------------*/
12499 /* genJumpTab - generates code for jump table                       */
12500 /*-----------------------------------------------------------------*/
12501 static void genJumpTab (iCode *ic)
12502 {
12503   symbol *jtab;
12504   char *l;
12505   pCodeOp *jt_offs;
12506   pCodeOp *jt_offs_hi;
12507   pCodeOp *jt_label;
12508
12509     FENTRY;
12510
12511     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12512     /* get the condition into accumulator */
12513     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12514     MOVA(l);
12515     /* multiply by three */
12516     pic16_emitcode("add","a,acc");
12517     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12518
12519     jtab = newiTempLabel(NULL);
12520     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12521     pic16_emitcode("jmp","@a+dptr");
12522     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12523
12524 #if 0
12525     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12526     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12527     emitSKPNC;
12528     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12530     pic16_emitpLabel(jtab->key);
12531
12532 #else
12533
12534     jt_offs = pic16_popGetTempReg(0);
12535     jt_offs_hi = pic16_popGetTempReg(1);
12536     jt_label = pic16_popGetLabel (jtab->key);
12537     //fprintf (stderr, "Creating jump table...\n");
12538
12539     // calculate offset into jump table (idx * sizeof (GOTO))
12540     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12541     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12542     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12543     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12544     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12545     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12546     pic16_emitpcode(POC_MOVWF , jt_offs);
12547
12548     // prepare PCLATx (set to first entry in jump table)
12549     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12550     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12551     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12552     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12553     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12554
12555     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12556     pic16_emitpcode(POC_ADDWF , jt_offs);
12557     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12558     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12559     emitSKPNC;
12560     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12561
12562     // release temporaries and prepare jump into table (new PCL --> WREG)
12563     pic16_emitpcode(POC_MOVFW , jt_offs);
12564     pic16_popReleaseTempReg (jt_offs_hi, 1);
12565     pic16_popReleaseTempReg (jt_offs, 0);
12566
12567     // jump into the table
12568     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12569
12570     pic16_emitpLabelFORCE(jtab->key);
12571 #endif
12572
12573     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12574 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12575
12576     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12577     /* now generate the jump labels */
12578     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12579          jtab = setNextItem(IC_JTLABELS(ic))) {
12580 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12581         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12582         
12583     }
12584     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12585
12586 }
12587
12588 /*-----------------------------------------------------------------*/
12589 /* genMixedOperation - gen code for operators between mixed types  */
12590 /*-----------------------------------------------------------------*/
12591 /*
12592   TSD - Written for the PIC port - but this unfortunately is buggy.
12593   This routine is good in that it is able to efficiently promote 
12594   types to different (larger) sizes. Unfortunately, the temporary
12595   variables that are optimized out by this routine are sometimes
12596   used in other places. So until I know how to really parse the 
12597   iCode tree, I'm going to not be using this routine :(.
12598 */
12599 static int genMixedOperation (iCode *ic)
12600 {
12601 #if 0
12602   operand *result = IC_RESULT(ic);
12603   sym_link *ctype = operandType(IC_LEFT(ic));
12604   operand *right = IC_RIGHT(ic);
12605   int ret = 0;
12606   int big,small;
12607   int offset;
12608
12609   iCode *nextic;
12610   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12611
12612   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12613
12614   nextic = ic->next;
12615   if(!nextic)
12616     return 0;
12617
12618   nextright = IC_RIGHT(nextic);
12619   nextleft  = IC_LEFT(nextic);
12620   nextresult = IC_RESULT(nextic);
12621
12622   pic16_aopOp(right,ic,FALSE);
12623   pic16_aopOp(result,ic,FALSE);
12624   pic16_aopOp(nextright,  nextic, FALSE);
12625   pic16_aopOp(nextleft,   nextic, FALSE);
12626   pic16_aopOp(nextresult, nextic, FALSE);
12627
12628   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12629
12630     operand *t = right;
12631     right = nextright;
12632     nextright = t; 
12633
12634     pic16_emitcode(";remove right +","");
12635
12636   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12637 /*
12638     operand *t = right;
12639     right = nextleft;
12640     nextleft = t; 
12641 */
12642     pic16_emitcode(";remove left +","");
12643   } else
12644     return 0;
12645
12646   big = AOP_SIZE(nextleft);
12647   small = AOP_SIZE(nextright);
12648
12649   switch(nextic->op) {
12650
12651   case '+':
12652     pic16_emitcode(";optimize a +","");
12653     /* if unsigned or not an integral type */
12654     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12655       pic16_emitcode(";add a bit to something","");
12656     } else {
12657
12658       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12659
12660       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12661         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12662         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12663       } else
12664         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12665
12666       offset = 0;
12667       while(--big) {
12668
12669         offset++;
12670
12671         if(--small) {
12672           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12673             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12674             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12675           }
12676
12677           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12678           emitSKPNC;
12679           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12680                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12681                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12682           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12684
12685         } else {
12686           pic16_emitcode("rlf","known_zero,w");
12687
12688           /*
12689             if right is signed
12690               btfsc  right,7
12691                addlw ff
12692           */
12693           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12694             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12695             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12696           } else {
12697             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12698           }
12699         }
12700       }
12701       ret = 1;
12702     }
12703   }
12704   ret = 1;
12705
12706 release:
12707   pic16_freeAsmop(right,NULL,ic,TRUE);
12708   pic16_freeAsmop(result,NULL,ic,TRUE);
12709   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12710   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12711   if(ret)
12712     nextic->generated = 1;
12713
12714   return ret;
12715 #else
12716   return 0;
12717 #endif
12718 }
12719 /*-----------------------------------------------------------------*/
12720 /* genCast - gen code for casting                                  */
12721 /*-----------------------------------------------------------------*/
12722 static void genCast (iCode *ic)
12723 {
12724   operand *result = IC_RESULT(ic);
12725   sym_link *ctype = operandType(IC_LEFT(ic));
12726   sym_link *rtype = operandType(IC_RIGHT(ic));
12727   sym_link *restype = operandType(IC_RESULT(ic));
12728   operand *right = IC_RIGHT(ic);
12729   int size, offset ;
12730
12731
12732     FENTRY;
12733
12734         /* if they are equivalent then do nothing */
12735 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12736 //              return ;
12737
12738         pic16_aopOp(result,ic,FALSE);
12739         pic16_aopOp(right,ic,FALSE) ;
12740
12741         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12742
12743
12744         /* if the result is a bit */
12745         if (AOP_TYPE(result) == AOP_CRY) {
12746         
12747                 /* if the right size is a literal then
12748                  * we know what the value is */
12749                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12750
12751                 if (AOP_TYPE(right) == AOP_LIT) {
12752                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12753                                 pic16_popGet(AOP(result),0));
12754
12755                         if (((int) operandLitValue(right))) 
12756                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12757                                         AOP(result)->aopu.aop_dir,
12758                                         AOP(result)->aopu.aop_dir);
12759                         else
12760                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12761                                         AOP(result)->aopu.aop_dir,
12762                                         AOP(result)->aopu.aop_dir);
12763                         goto release;
12764                 }
12765
12766                 /* the right is also a bit variable */
12767                 if (AOP_TYPE(right) == AOP_CRY) {
12768                         emitCLRC;
12769                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12770
12771                         pic16_emitcode("clrc","");
12772                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12773                                 AOP(right)->aopu.aop_dir,
12774                                 AOP(right)->aopu.aop_dir);
12775                         pic16_aopPut(AOP(result),"c",0);
12776                         goto release ;
12777                 }
12778
12779                 /* we need to or */
12780                 if (AOP_TYPE(right) == AOP_REG) {
12781                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12782                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12783                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12784                 }
12785                 pic16_toBoolean(right);
12786                 pic16_aopPut(AOP(result),"a",0);
12787                 goto release ;
12788         }
12789
12790         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12791           int offset = 1;
12792
12793                 size = AOP_SIZE(result);
12794
12795                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12796
12797                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12798                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12799                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12800
12801                 while (size--)
12802                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12803
12804                 goto release;
12805         }
12806
12807         if(IS_BITFIELD(getSpec(restype))
12808           && IS_BITFIELD(getSpec(rtype))) {
12809           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12810         }
12811
12812         /* if they are the same size : or less */
12813         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12814
12815                 /* if they are in the same place */
12816                 if (pic16_sameRegs(AOP(right),AOP(result)))
12817                         goto release;
12818
12819                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12820 #if 0
12821                 if (IS_PTR_CONST(rtype))
12822 #else
12823                 if (IS_CODEPTR(rtype))
12824 #endif
12825                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12826
12827 #if 0
12828                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12829 #else
12830                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12831 #endif
12832                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12833
12834 #if 0
12835                 if(AOP_TYPE(right) == AOP_IMMD) {
12836                   pCodeOp *pcop0, *pcop1, *pcop2;
12837                   symbol *sym = OP_SYMBOL( right );
12838
12839                         size = AOP_SIZE(result);
12840                         /* low */
12841                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12842                         /* high */
12843                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12844                         /* upper */
12845                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12846         
12847                         if (size == 3) {
12848                                 pic16_emitpcode(POC_MOVLW, pcop0);
12849                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12850                                 pic16_emitpcode(POC_MOVLW, pcop1);
12851                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12852                                 pic16_emitpcode(POC_MOVLW, pcop2);
12853                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12854                         } else
12855                         if (size == 2) {
12856                                 pic16_emitpcode(POC_MOVLW, pcop0);
12857                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12858                                 pic16_emitpcode(POC_MOVLW, pcop1);
12859                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12860                         } else {
12861                                 pic16_emitpcode(POC_MOVLW, pcop0);
12862                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12863                         }
12864                 } else
12865 #endif
12866                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12867                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12868                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12869                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12870                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12871                         if(AOP_SIZE(result) <2)
12872                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12873                 } else {
12874                         /* if they in different places then copy */
12875                         size = AOP_SIZE(result);
12876                         offset = 0 ;
12877                         while (size--) {
12878                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12879                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12880                                 offset++;
12881                         }
12882                 }
12883                 goto release;
12884         }
12885
12886         /* if the result is of type pointer */
12887         if (IS_PTR(ctype)) {
12888           int p_type;
12889           sym_link *type = operandType(right);
12890           sym_link *etype = getSpec(type);
12891
12892                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12893
12894                 /* pointer to generic pointer */
12895                 if (IS_GENPTR(ctype)) {
12896                   char *l = zero;
12897             
12898                         if (IS_PTR(type)) 
12899                                 p_type = DCL_TYPE(type);
12900                         else {
12901                 /* we have to go by the storage class */
12902                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12903
12904 /*              if (SPEC_OCLS(etype)->codesp )  */
12905 /*                  p_type = CPOINTER ;  */
12906 /*              else */
12907 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12908 /*                      p_type = FPOINTER ; */
12909 /*                  else */
12910 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12911 /*                          p_type = PPOINTER; */
12912 /*                      else */
12913 /*                          if (SPEC_OCLS(etype) == idata ) */
12914 /*                              p_type = IPOINTER ; */
12915 /*                          else */
12916 /*                              p_type = POINTER ; */
12917             }
12918                 
12919             /* the first two bytes are known */
12920       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12921             size = GPTRSIZE - 1; 
12922             offset = 0 ;
12923             while (size--) {
12924               if(offset < AOP_SIZE(right)) {
12925                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12926                 pic16_mov2f(AOP(result), AOP(right), offset);
12927 /*
12928                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12929                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12930                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12931                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12932                 } else { 
12933                   
12934                   pic16_aopPut(AOP(result),
12935                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12936                          offset);
12937                 }
12938 */
12939               } else 
12940                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12941               offset++;
12942             }
12943             /* the last byte depending on type */
12944             switch (p_type) {
12945             case IPOINTER:
12946             case POINTER:
12947                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12948                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12949 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12950                 break;
12951
12952             case CPOINTER:
12953                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12954                 break;
12955
12956             case FPOINTER:
12957               pic16_emitcode(";BUG!? ","%d",__LINE__);
12958                 l = one;
12959                 break;
12960             case PPOINTER:
12961               pic16_emitcode(";BUG!? ","%d",__LINE__);
12962                 l = "#0x03";
12963                 break;
12964
12965             case GPOINTER:
12966                 if (GPTRSIZE > AOP_SIZE(right)) {
12967                   // assume data pointer... THIS MIGHT BE WRONG!
12968                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12969                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12970                 } else {
12971                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12972                 }
12973               break;
12974               
12975             default:
12976                 /* this should never happen */
12977                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12978                        "got unknown pointer type");
12979                 exit(1);
12980             }
12981             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12982             goto release ;
12983         }
12984         
12985         
12986         assert( 0 );
12987         /* just copy the pointers */
12988         size = AOP_SIZE(result);
12989         offset = 0 ;
12990         while (size--) {
12991             pic16_aopPut(AOP(result),
12992                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12993                    offset);
12994             offset++;
12995         }
12996         goto release ;
12997     }
12998     
12999
13000
13001     /* so we now know that the size of destination is greater
13002     than the size of the source.
13003     Now, if the next iCode is an operator then we might be
13004     able to optimize the operation without performing a cast.
13005     */
13006     if(genMixedOperation(ic))
13007       goto release;
13008
13009     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13010     
13011     /* we move to result for the size of source */
13012     size = AOP_SIZE(right);
13013     offset = 0 ;
13014
13015     while (size--) {
13016       if(!_G.resDirect)
13017         pic16_mov2f(AOP(result), AOP(right), offset);
13018       offset++;
13019     }
13020
13021     /* now depending on the sign of the destination */
13022     size = AOP_SIZE(result) - AOP_SIZE(right);
13023     /* if unsigned or not an integral type */
13024     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13025       while (size--)
13026         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13027     } else {
13028       /* we need to extend the sign :( */
13029
13030       if(size == 1) {
13031         /* Save one instruction of casting char to int */
13032         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13033         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13034         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13035       } else {
13036         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13037
13038         if(offset)
13039           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13040         else
13041           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13042         
13043         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13044
13045         while (size--)
13046           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13047       }
13048     }
13049
13050 release:
13051     pic16_freeAsmop(right,NULL,ic,TRUE);
13052     pic16_freeAsmop(result,NULL,ic,TRUE);
13053
13054 }
13055
13056 /*-----------------------------------------------------------------*/
13057 /* genDjnz - generate decrement & jump if not zero instrucion      */
13058 /*-----------------------------------------------------------------*/
13059 static int genDjnz (iCode *ic, iCode *ifx)
13060 {
13061     symbol *lbl, *lbl1;
13062     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13063
13064     if (!ifx)
13065         return 0;
13066     
13067     /* if the if condition has a false label
13068        then we cannot save */
13069     if (IC_FALSE(ifx))
13070         return 0;
13071
13072     /* if the minus is not of the form 
13073        a = a - 1 */
13074     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13075         !IS_OP_LITERAL(IC_RIGHT(ic)))
13076         return 0;
13077
13078     if (operandLitValue(IC_RIGHT(ic)) != 1)
13079         return 0;
13080
13081     /* if the size of this greater than one then no
13082        saving */
13083     if (getSize(operandType(IC_RESULT(ic))) > 1)
13084         return 0;
13085
13086     /* otherwise we can save BIG */
13087     lbl = newiTempLabel(NULL);
13088     lbl1= newiTempLabel(NULL);
13089
13090     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13091     
13092     if (IS_AOP_PREG(IC_RESULT(ic))) {
13093         pic16_emitcode("dec","%s",
13094                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13095         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13096         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13097     } else {    
13098
13099
13100       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13101       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13102
13103       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13104       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13105
13106     }
13107     
13108     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13109     ifx->generated = 1;
13110     return 1;
13111 }
13112
13113 /*-----------------------------------------------------------------*/
13114 /* genReceive - generate code for a receive iCode                  */
13115 /*-----------------------------------------------------------------*/
13116 static void genReceive (iCode *ic)
13117 {    
13118
13119   FENTRY;
13120
13121 #if 0
13122   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13123         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13124 #endif
13125 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13126
13127   if (isOperandInFarSpace(IC_RESULT(ic))
13128       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13129           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13130
13131     int size = getSize(operandType(IC_RESULT(ic)));
13132     int offset =  pic16_fReturnSizePic - size;
13133
13134       assert( 0 );
13135       while (size--) {
13136         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13137                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13138                       offset++;
13139         }
13140
13141       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13142
13143       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13144       size = AOP_SIZE(IC_RESULT(ic));
13145       offset = 0;
13146       while (size--) {
13147         pic16_emitcode ("pop","acc");
13148         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13149       }
13150   } else {
13151     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13152     _G.accInUse++;
13153     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13154     _G.accInUse--;
13155
13156     /* set pseudo stack pointer to where it should be - dw*/
13157     GpsuedoStkPtr = ic->parmBytes;
13158
13159     /* setting GpsuedoStkPtr has side effects here: */
13160     assignResultValue(IC_RESULT(ic), 0);
13161   }
13162
13163   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13164 }
13165
13166 /*-----------------------------------------------------------------*/
13167 /* genDummyRead - generate code for dummy read of volatiles        */
13168 /*-----------------------------------------------------------------*/
13169 static void
13170 genDummyRead (iCode * ic)
13171 {
13172   operand *op;
13173   int i;
13174
13175   op = IC_RIGHT(ic);
13176   if (op && IS_SYMOP(op)) {
13177     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13178       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13179       return;
13180     }
13181     pic16_aopOp (op, ic, FALSE);
13182     for (i=0; i < AOP_SIZE(op); i++) {
13183       // may need to protect this from the peepholer -- this is not nice but works...
13184       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13185       pic16_mov2w (AOP(op),i);
13186       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13187     } // for i
13188     pic16_freeAsmop (op, NULL, ic, TRUE);
13189   } else if (op) {
13190     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13191   } // if
13192 }
13193
13194 /*-----------------------------------------------------------------*/
13195 /* genpic16Code - generate code for pic16 based controllers        */
13196 /*-----------------------------------------------------------------*/
13197 /*
13198  * At this point, ralloc.c has gone through the iCode and attempted
13199  * to optimize in a way suitable for a PIC. Now we've got to generate
13200  * PIC instructions that correspond to the iCode.
13201  *
13202  * Once the instructions are generated, we'll pass through both the
13203  * peep hole optimizer and the pCode optimizer.
13204  *-----------------------------------------------------------------*/
13205
13206 void genpic16Code (iCode *lic)
13207 {
13208   iCode *ic;
13209   int cln = 0;
13210
13211     lineHead = lineCurr = NULL;
13212
13213     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13214     pic16_addpBlock(pb);
13215
13216 #if 0
13217     /* if debug information required */
13218     if (options.debug && currFunc) {
13219       if (currFunc) {
13220         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13221       }
13222     }
13223 #endif
13224
13225     for (ic = lic ; ic ; ic = ic->next ) {
13226
13227       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13228       if ( cln != ic->lineno ) {
13229         if ( options.debug ) {
13230           debugFile->writeCLine (ic);
13231         }
13232         
13233         if(!options.noCcodeInAsm) {
13234           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13235               printCLine(ic->filename, ic->lineno)));
13236         }
13237
13238         cln = ic->lineno ;
13239       }
13240         
13241       if(options.iCodeInAsm) {
13242         char *l;
13243
13244           /* insert here code to print iCode as comment */
13245           l = Safe_strdup(printILine(ic));
13246           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13247       }
13248         
13249       /* if the result is marked as
13250        * spilt and rematerializable or code for
13251        * this has already been generated then
13252        * do nothing */
13253       if (resultRemat(ic) || ic->generated ) 
13254         continue ;
13255         
13256       /* depending on the operation */
13257       switch (ic->op) {
13258         case '!' :
13259           pic16_genNot(ic);
13260           break;
13261             
13262         case '~' :
13263           pic16_genCpl(ic);
13264           break;
13265             
13266         case UNARYMINUS:
13267           genUminus (ic);
13268           break;
13269             
13270         case IPUSH:
13271           genIpush (ic);
13272           break;
13273             
13274         case IPOP:
13275           /* IPOP happens only when trying to restore a 
13276            * spilt live range, if there is an ifx statement
13277            * following this pop then the if statement might
13278            * be using some of the registers being popped which
13279            * would destroy the contents of the register so
13280            * we need to check for this condition and handle it */
13281            if (ic->next
13282              && ic->next->op == IFX
13283              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13284                genIfx (ic->next,ic);
13285           else
13286             genIpop (ic);
13287           break; 
13288             
13289         case CALL:
13290           genCall (ic);
13291           break;
13292             
13293         case PCALL:
13294           genPcall (ic);
13295           break;
13296             
13297         case FUNCTION:
13298           genFunction (ic);
13299           break;
13300             
13301         case ENDFUNCTION:
13302           genEndFunction (ic);
13303           break;
13304             
13305         case RETURN:
13306           genRet (ic);
13307           break;
13308             
13309         case LABEL:
13310           genLabel (ic);
13311           break;
13312             
13313         case GOTO:
13314           genGoto (ic);
13315           break;
13316             
13317         case '+' :
13318           pic16_genPlus (ic) ;
13319           break;
13320             
13321         case '-' :
13322           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13323             pic16_genMinus (ic);
13324           break;
13325
13326         case '*' :
13327           genMult (ic);
13328           break;
13329             
13330         case '/' :
13331           genDiv (ic) ;
13332           break;
13333             
13334         case '%' :
13335           genMod (ic);
13336           break;
13337             
13338         case '>' :
13339           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13340           break;
13341             
13342         case '<' :
13343           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13344           break;
13345             
13346         case LE_OP:
13347         case GE_OP:
13348         case NE_OP:
13349           /* note these two are xlated by algebraic equivalence
13350            * during parsing SDCC.y */
13351           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13352             "got '>=' or '<=' shouldn't have come here");
13353           break;
13354
13355         case EQ_OP:
13356           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13357           break;            
13358             
13359         case AND_OP:
13360           genAndOp (ic);
13361           break;
13362             
13363         case OR_OP:
13364           genOrOp (ic);
13365           break;
13366             
13367         case '^' :
13368           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13369           break;
13370             
13371         case '|' :
13372           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13373           break;
13374             
13375         case BITWISEAND:
13376           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13377           break;
13378             
13379         case INLINEASM:
13380           genInline (ic);
13381           break;
13382             
13383         case RRC:
13384           genRRC (ic);
13385           break;
13386             
13387         case RLC:
13388           genRLC (ic);
13389           break;
13390             
13391         case GETHBIT:
13392           genGetHbit (ic);
13393           break;
13394             
13395         case LEFT_OP:
13396           genLeftShift (ic);
13397           break;
13398             
13399         case RIGHT_OP:
13400           genRightShift (ic);
13401           break;
13402             
13403         case GET_VALUE_AT_ADDRESS:
13404           genPointerGet(ic);
13405           break;
13406             
13407         case '=' :
13408           if (POINTER_SET(ic))
13409             genPointerSet(ic);
13410           else
13411             genAssign(ic);
13412           break;
13413             
13414         case IFX:
13415           genIfx (ic,NULL);
13416           break;
13417             
13418         case ADDRESS_OF:
13419           genAddrOf (ic);
13420           break;
13421             
13422         case JUMPTABLE:
13423           genJumpTab (ic);
13424           break;
13425             
13426         case CAST:
13427           genCast (ic);
13428           break;
13429             
13430         case RECEIVE:
13431           genReceive(ic);
13432           break;
13433             
13434         case SEND:
13435           addSet(&_G.sendSet,ic);
13436           break;
13437
13438         case DUMMY_READ_VOLATILE:
13439           genDummyRead (ic);
13440           break;
13441
13442         default :
13443           ic = ic;
13444       }
13445     }
13446
13447
13448     /* now we are ready to call the
13449        peep hole optimizer */
13450     if (!options.nopeep)
13451       peepHole (&lineHead);
13452
13453     /* now do the actual printing */
13454     printLine (lineHead, codeOutFile);
13455
13456 #ifdef PCODE_DEBUG
13457     DFPRINTF((stderr,"printing pBlock\n\n"));
13458     pic16_printpBlock(stdout,pb);
13459 #endif
13460
13461     return;
13462 }
13463